Woocommerce Scraper avatar

Woocommerce Scraper

Pricing

$19.99/month + usage

Go to Apify Store
Woocommerce Scraper

Woocommerce Scraper

WooCommerce Scraper extracts product data from WooCommerce stores with accuracy. Collect product names, prices, SKUs, categories, images, and availability for research, monitoring, and catalog building. Ideal for eCommerce analysis and automation.

Pricing

$19.99/month + usage

Rating

5.0

(1)

Developer

Scraper Engine

Scraper Engine

Maintained by Community

Actor stats

0

Bookmarked

13

Total users

1

Monthly active users

15 hours

Issues response

15 hours ago

Last modified

Share

WooCommerce Scraper — Products, Prices, Stock and Reviews

WooCommerce Scraper reads any WooCommerce store's public Store API and returns its products as structured JSON — name, SKU, price in real currency units, stock status, average rating, review count, images, categories, tags and attributes. Switch the Resource input and the same run pulls categories, brands, tags, attributes, reviews, pages or posts instead. No login, API key or WooCommerce REST API credentials are required. Start a run below with a single store URL.


What is WooCommerce Scraper?

WooCommerce Scraper is an Apify Actor that reads a WooCommerce store's public WooCommerce Store API (/wp-json/wc/store/*) and WordPress REST API (/wp-json/wp/v2/*) and returns the results as structured JSON — one row per product, category, review, page or whichever resource you select. No WooCommerce account, REST API consumer key/secret or store login is required: it reads the same public endpoints the store's own shop page calls in a browser. It's built for competitor-pricing teams, dropshippers, catalogue researchers and AI engineers who need a store's data as clean, typed JSON rather than parsed HTML.


What WooCommerce product data is publicly available to scrape?

Any WooCommerce store running version 4.0 or newer publishes its product catalogue, taxonomy and reviews through the Store API without requiring a login. Order, customer and checkout data are never public — they sit behind the store's own wp-admin session or a WooCommerce REST API key the store owner has to issue.

Data categoryPublicly availableRestricted
Product listing (name, price, stock, images)wc/store/products
Product taxonomy (categories, tags, attributes)Brands taxonomy only if the WooCommerce Brands plugin is installed — otherwise brands answers 200 with an empty list
Product reviews via the Store API reviews resource
Product reviews via WordPress wp/v2/comments⚠️ Hidden from logged-out clientsWooCommerce filters review-type comments out of that endpoint — use resource: "reviews" instead
Pages and posts (wp/v2/pages, wp/v2/posts)
Registered users (wp/v2/users)✅ on some stores❌ Disabled (404) on many hardened stores
Draft, private or trashed productsNever exposed — the Store API only publishes what a shopper can see
Orders, customers, coupons, checkoutwp-admin login or a WooCommerce REST API consumer key/secret

WooCommerce Scraper only returns publicly visible data — what any shopper's browser already loads. Nothing behind a login wall, an admin session or a REST API key.


What data can I extract with WooCommerce Scraper?

Each product row carries identity, taxonomy and content fields alongside computed pricing, stock and rating metrics. Every value comes straight from the store's own API response — a field the store didn't send comes back null, never a guess.

🏷️ Identity, taxonomy and content fields

FieldDescription
urlProduct permalink
idWooCommerce product ID
nameProduct name (HTML entities decoded)
slugURL slug
parentParent product ID (0 for a standalone product; the parent's ID on a variation row)
typesimple, variable, grouped, external or variation
variationVariation attribute values, present on variation rows
skuStore-assigned SKU
short_description / descriptionRendered as Markdown, plain text or raw HTML, per the Output Format input
categories / tags / brands / attributesArrays of taxonomy term objects exactly as the store publishes them
imagesArray of image objects (src, thumbnail, srcset, alt, …)
variationsArray of variation ID/attribute pairs (expand into full rows with Include Variations)
grouped_productsChild product IDs on a grouped product
store / resource_typeThe store URL this row came from, and the resource it was fetched under

📊 Pricing, stock and rating fields

FieldDescription
pricesRaw store object: price, regular_price, sale_price, price_range, currency_code, currency_symbol, currency_minor_unit, currency_decimal_separator, currency_thousand_separator, currency_prefix, currency_suffix
price_value / regular_price_value / sale_price_valueThe prices above divided by the store's own minor unit, as real numbers (60.0, not "60")
currency_codeISO currency code, flattened alongside price_value for convenience
on_saletrue/false
average_ratingString exactly as the store publishes it, e.g. "4.50"
review_countInteger, kept even when it's 0
is_in_stock / is_on_backorderStock flags
low_stock_remainingUnits left, or null if the store doesn't publish low-stock counts
sold_individuallytrue if only one unit can be bought per order
stock_availability{ text, class } stock-status label the store shows on the page
has_options / is_purchasableVariable-product and purchasability flags
add_to_cart{ minimum, maximum, multiple_of, single_text, url } order-quantity rules
extensionsWhatever WooCommerce or third-party plugin extension blocks the store attaches (e.g. name-your-price data), or {}

Switching Resource away from products returns categories, brands, tags, attributes, reviews, pages, posts, comments, post-categories, post-tags or users exactly as the store's own API publishes each record, with store and resource_type added to every row.

🤖 Add-on: Need data from other storefronts too?

If you're benchmarking a WooCommerce store against Shopify competitors in the same category, pair this with Shopify Products Scraper for the equivalent catalogue read on Shopify storefronts.


How does WooCommerce Scraper differ from the official WooCommerce REST API?

WooCommerce's own REST API (wp-json/wc/v3) requires the store owner to generate a consumer key and secret in WooCommerce → Settings → Advanced → REST API before a single request works, and every call must authenticate with that key pair (woocommerce.github.io, checked 2026-08-16). That makes it unusable for reading a store you don't own or administer — exactly the case for competitor research, price monitoring and market surveys.

FeatureWooCommerce REST API (wc/v3)WooCommerce Scraper
Read a store you don't own❌ needs a consumer key/secret the store owner issues you✅ reads the same public Store API a shopper's browser calls
SetupStore owner generates keys; you configure Basic Auth or OAuth1.0aPaste a store URL and run
Multiple unrelated stores in one run❌ separate key pair per store✅ one run, any number of URLs in startUrls
Published rate limitNot published in WooCommerce's own docsSelf-paced, with automatic proxy escalation only when a store pushes back
Data returnedWhatever the key's scope allows, including orders and customersProducts, taxonomy, reviews and WordPress content — public storefront data only, never orders or customers
Output shapeRaw wc/v3 REST objects you normalize yourselfPrices pre-converted to real currency units alongside the raw store values

Use the WooCommerce REST API when you own the store and need write access, orders or customer data. Use WooCommerce Scraper for read-only catalogue collection across stores you don't control, without asking the merchant for a key.


How to use WooCommerce Scraper

  1. Open WooCommerce Scraper on the Apify Store and click Try for free (or Start, if you already have it saved) to open the input form in Apify Console.
  2. Fill in startUrls with at least one store address — a bare domain (https://example.com) or a sub-directory install (https://example.com/shop) both work.
  3. Optionally set resource, sort, stock, category, min_price/max_price or the other product filters to narrow what comes back.
  4. Click Start.
  5. Open the run's dataset and export it as JSON, CSV, Excel, XML or HTML, or pull it through the Apify API.

How to scale to bulk product extraction

startUrls is an array — add as many store addresses as you need in one run, and each gets its own store value on every row. For a store list too long to paste in, point dev_fileupload at a hosted text or JSON file listing one URL per line (or a JSON array); its URLs are merged into the run automatically.


What can you do with WooCommerce product data?

  • 💰 Competitor price monitoring — a pricing analyst schedules a daily run across rival stores and diffs price_value and on_sale per sku to catch markdowns as they happen.
  • 📦 Inventory and backorder tracking — an ops analyst watches is_in_stock, is_on_backorder and low_stock_remaining to see what a competitor is about to sell out of.
  • 🗂️ Catalogue and PIM enrichment — a catalogue manager pulls name, description, images, categories and attributes to seed or refresh an internal product database.
  • Review mining — a CX researcher sets resource: "reviews" to collect rating, reviewer and review text for sentiment analysis without touching the storefront HTML.
  • 🤖 AI shopping-assistant / RAG pipelines — an AI engineer indexes name, description and attributes into a vector store so an agent can answer product questions or compare SKUs across stores without re-scraping. The typed JSON output is a ready tool response for any agent framework that can call the Apify API.

How does WooCommerce Scraper handle rate limits and blocking?

Requests start with no proxy. If a store refuses a direct request, the run escalates automatically — Apify datacenter proxy first, then Apify residential proxy, retrying up to 3 times on the residential tier with a 2-second pause between attempts. Once a tier answers 200 it is kept for the rest of the run. A 4xx response that isn't a block signal (anything other than 401, 403, 407 or 429) is treated as the request's own fault and returned immediately rather than escalated, since a bigger proxy budget can't fix a bad filter value. If an endpoint answers 200 with a body that isn't valid JSON, that's reported as the store likely serving an HTML challenge page rather than silently returning an empty result. Between stores in a multi-store run, the actor pauses one second. No CAPTCHA solving is performed.


⬇️ Input

Required per schema: none — but a run needs at least one store URL in startUrls or url to produce data.

ParameterRequiredTypeDescriptionExample value
startUrlsNoarrayStore home pages. A bare domain works, and a sub-directory install is kept. Fill this or url.["https://porterandyork.com"]
urlNoarrayAlternative to startUrls.[]
limitNointegerMax records per store (1–1000, default 10). Variations from Include Variations are returned on top of it.50
resourceNostringproducts (default), categories, brands, tags, attributes, reviews, pages, posts, comments, post-categories, post-tags, users."products"
include_variationsNobooleanAlso fetch every variation of the variable products found (default false).true
formatNostringmd (default), text or html — for description, short_description and review bodies."md"
sortNostringdate (default), modified, id, include, title, slug, price, popularity, rating, menu_order, comment_count, or "" for the store's own order. Unsupported values for the chosen resource are logged and skipped."price"
orderNostring"" (default, auto), asc or desc. Applied only when sort is supported by the resource."asc"
searchNostringText search, run by the store. Not supported for attributes or reviews."steak"
skuNostringExact SKU. Products only."PY1261"
ratingNostring"" (default, any), 15. Products only; the Store API honours one value."5"
min_priceNointegerMinimum price, in the store's minor currency unit (1999 = 19.99 on a 2-decimal store). Products only.1000
max_priceNointegerMaximum price, same minor-unit rule. Products only.5000
categoryNostringComma-separated category term IDs. Run once with resource: "categories" to get them. Products only."21,34"
tagNostringComma-separated tag term IDs. Products only."12"
product_typeNostring"" (default, any), simple, grouped, external, variable, wbs_bundle, variation. Products only."variable"
stockNostring"" (default, any), instock, outofstock, onbackorder. Products only."instock"
featuredNobooleanFeatured products only (default false). Products only.false
saleNobooleanOn-sale products only (default false). Products only.true
proxyConfigurationNoobjectApify proxy settings. By default no proxy is used; the actor escalates on its own if a store refuses the direct request.{"useApifyProxy": false}
dev_proxy_configNostringYour own http(s)://user:pass@host:port proxy, used instead of the Apify proxy. SOCKS is not supported.""
dev_custom_headersNostringExtra HTTP headers: a JSON array of {name, value}, a JSON object, or Name: value lines.""
dev_custom_cookiesNostringExtra HTTP cookies, same three accepted shapes.""
dev_transform_fieldsNostringComma-separated field paths to keep in the output, e.g. id,name,prices.price.""
dev_dataset_nameNostringWrite to a named dataset instead of the default one. Masks: {ACTOR}, {DATE}, {TIME}.""
dev_dataset_clearNobooleanEmpty the named dataset above first (default false). No effect without dev_dataset_name.false
dev_no_stripNobooleanKeep null/empty-string/empty-array/empty-object fields in the output (default false). Booleans and zeros are always kept.false
dev_fileuploadNostringURL of a text or JSON file holding one store URL per line, or a JSON array of URLs.""

⚠️ min_price/max_price match a variable product if any of its variations falls in the range — so a 5070 filter can return a product whose own price_value is 15. Set include_variations: true to get one row per variation with its own price if you need an exact match.

Example input

{
"startUrls": ["https://porterandyork.com", "https://mercantile.wordpress.org"],
"limit": 100,
"resource": "products",
"sale": true,
"stock": "instock",
"max_price": 5000,
"sort": "price",
"order": "asc",
"include_variations": true,
"format": "md",
"proxyConfiguration": { "useApifyProxy": false }
}

⬆️ Output

Results land in the Actor's dataset as typed JSON, exportable as JSON, CSV, Excel, XML or HTML from Apify Console or via the API. Each record written to the dataset is billed once under the row_result pricing event; a store that doesn't answer, or a resource that returns no records, is never charged.

Example output

{
"url": "https://porterandyork.com/product/buy-porterhouse-steak-online/",
"id": 15,
"name": "Porterhouse Steak",
"slug": "buy-porterhouse-steak-online",
"parent": 0,
"type": "variable",
"sku": "PY1261",
"short_description": "A cross between the tenderloin and the strip.",
"description": "Hand-cut and dry-aged porterhouse steak, USDA Prime.",
"on_sale": false,
"prices": {
"price": "6000",
"regular_price": "6000",
"sale_price": "6000",
"price_range": { "min_amount": "6000", "max_amount": "9500" },
"currency_code": "USD",
"currency_symbol": "$",
"currency_minor_unit": 2,
"currency_decimal_separator": ".",
"currency_thousand_separator": ",",
"currency_prefix": "$",
"currency_suffix": ""
},
"price_value": 60.0,
"regular_price_value": 60.0,
"sale_price_value": 60.0,
"currency_code": "USD",
"average_rating": "4.50",
"review_count": 12,
"images": [
{ "id": 1234, "src": "https://porterandyork.com/wp-content/uploads/porterhouse.jpg", "alt": "" }
],
"categories": [
{ "id": 21, "name": "Beef", "slug": "beef", "link": "https://porterandyork.com/product-category/beef/" }
],
"tags": [],
"brands": [],
"attributes": [
{ "id": 1, "name": "Size", "taxonomy": "pa_size", "has_variations": true, "terms": [] }
],
"variations": [
{ "id": 1230, "attributes": [{ "name": "Size", "value": "24-oz-usda-prime" }] }
],
"grouped_products": [],
"has_options": true,
"is_purchasable": true,
"is_in_stock": true,
"is_on_backorder": false,
"low_stock_remaining": null,
"sold_individually": false,
"stock_availability": { "text": "", "class": "in-stock" },
"add_to_cart": {
"minimum": 1,
"maximum": 9999,
"multiple_of": 1,
"single_text": "Add to cart",
"url": "https://porterandyork.com/product/buy-porterhouse-steak-online/"
},
"extensions": {},
"store": "https://porterandyork.com",
"resource_type": "products"
}

Other resources (categories, brands, tags, attributes, reviews, pages, posts, comments, post-categories, post-tags, users) are written to the same dataset shape-for-shape as the store's own API publishes them, with store and resource_type added to every row.


How does it work?

WooCommerce Scraper calls the same public JSON endpoints a browser loads when it visits a WooCommerce storefront — the Store API (/wp-json/wc/store/*) for products and product taxonomy, and the WordPress REST API (/wp-json/wp/v2/*) for pages, posts, comments and users. No browser is launched and no JavaScript is rendered; these are direct HTTP calls. Each store URL is normalised so both a bare domain and a sub-directory install resolve, and the chosen resource is paged with per_page/offset until your limit is reached. Requests start on a direct connection and only route through an Apify datacenter or residential proxy if the store pushes back. Only publicly visible data is ever returned — nothing behind a login. Because every WooCommerce store publishes this API in the same shape, the output schema stays the same regardless of which theme or page builder the store is running.


Integrations

WooCommerce Scraper works with the tools you already use for automation and analysis — no plugin required, since it's just an Apify Actor reachable over the standard Apify API.

Calling WooCommerce Scraper programmatically

from apify_client import ApifyClient
client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("scraper-engine/woocommerce-scraper").call(run_input={
"startUrls": ["https://porterandyork.com"],
"limit": 100,
"resource": "products",
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["name"], item.get("price_value"))

Works in Go, Ruby, Node.js, cURL — any language that can make an HTTP request against the Apify API.

No-code tools (n8n, Make, LangChain)

In n8n, use the HTTP Request node pointed at the Actor's run-sync-get-dataset-items endpoint with your API token, or the dedicated Apify node if you have it installed. In Make, the Apify app's "Run an Actor" module accepts the same startUrls/resource input and returns the dataset items to the next module. In LangChain, the ApifyWrapper/Apify Actor tool can call this Actor and load its dataset directly as Document objects for a retrieval pipeline.


Scraping publicly available product data is generally lawful — this Actor returns only what any shopper's browser can already load from a storefront, without bypassing a login, password or paywall. Product catalogues, prices and SKUs are business/product data, not personal data, so GDPR and CCPA do not attach to this Actor's core output; the relevant framework instead is the store's terms of service and whatever database-rights protections apply to a compiled catalogue in your jurisdiction. If you set resource: "reviews", review text is content the reviewer chose to publish on the store; treat any reviewer name in it accordingly. Consult legal counsel if your use case involves bulk storage or redistribution of a store's data.


Frequently asked questions

What WooCommerce product fields does WooCommerce Scraper return?

The top fields are name, sku, price_value (with regular_price_value/sale_price_value), is_in_stock and average_rating. See What data can I extract above for the full field tables.

Does WooCommerce Scraper require a WooCommerce account or login?

No. It reads the store's public Store API and WordPress REST API exactly as a shopper's browser would — no account, consumer key/secret or store login is needed.

How many products can I extract in one run?

Up to limit per store (1–1000, default 10). Setting include_variations: true adds every variation of the variable products found on top of that number.

What happens if a product is out of stock or removed from the store?

An out-of-stock product still comes back, with is_in_stock: false, is_on_backorder set accordingly and low_stock_remaining populated if the store publishes it. A product that has been unpublished, put back into draft or trashed never appears at all — the Store API only exposes what a shopper can currently see, so there's no separate "removed" status to check for.

Can I scrape multiple WooCommerce stores at once?

Yes. Put every store URL in startUrls, or point dev_fileupload at a hosted file listing them. Each row carries its store URL so you can tell rows from different stores apart in one dataset.

Does WooCommerce Scraper work with Claude, ChatGPT and other AI agent tools?

Yes, as an HTTP endpoint any agent framework can call through the Apify API — the JSON output is typed and consistent, so it drops straight into a tool call or RAG pipeline without extra parsing.

How does WooCommerce Scraper compare to other WooCommerce scrapers?

Most WooCommerce scrapers only read the product listing. WooCommerce Scraper's resource switch also reads categories, brands, tags, attributes, reviews and the store's WordPress pages, posts and comments from the same run, and it tracks which sort and filter values each endpoint actually accepts — a request that would otherwise get an HTTP 400 from the store is detected and skipped, with a log line, instead of silently returning zero rows.

Does WooCommerce Scraper return data in a format LLMs can use directly?

Yes. Typed, normalized JSON with consistent field names across runs — no HTML parsing, no selectors. Pass it directly to an LLM, index it into a vector store, or feed it to an agent tool.

What happens when a WooCommerce store changes its theme or anti-bot setup?

The Store API and WordPress REST API this Actor reads are WooCommerce's own stable data endpoints, not the rendered storefront page, so a theme change doesn't change the output schema. No specific update turnaround is published for anti-bot changes on a store's side.

Can I use WooCommerce Scraper without managing proxies or browser infrastructure?

Yes. There's no browser to configure — requests are direct HTTP calls — and escalation through an Apify datacenter or residential proxy happens automatically if a store pushes back, with no proxy setup required unless you want to supply your own.

Which fields work best for AI training data and RAG indexing?

For RAG, index name, description and short_description as descriptive text alongside attributes and categories for structured lookups. For training data, price_value, average_rating, review_count and is_in_stock are the most consistently structured fields across every product row. All fields return as typed primitives — strings, numbers, booleans or arrays — never mixed types.


ScraperWhat it extracts
Shopify Products ScraperA Shopify store's full product catalogue: variants, SKUs, price and stock
Shopify Store ScraperStore-level profile: theme, installed apps, catalogue size
Shopify Merchant ScraperStore contact details, socials and tech stack
Alibaba Listings ScraperAlibaba product listings: prices, MOQ, supplier details
Amazon Product Details ScraperProduct details from Amazon listing pages
eBay Product Listing ScraperProduct data from eBay search and listing pages

Your feedback

Found a bug, or missing a field you need from a WooCommerce store? Open an issue on this Actor's Issues tab in Apify Console — that's the fastest way to reach the maintainer directly.