Shopify & WooCommerce Scraper and Price Tracker
Pricing
from $1.50 / 1,000 product returneds
Shopify & WooCommerce Scraper and Price Tracker
Shopify scraper and WooCommerce scraper in one: export every product (prices, sale prices, variants, SKUs, barcodes, stock, weights, images) to JSON, CSV or Excel, and track price drops, restocks, new and removed products between runs.
Pricing
from $1.50 / 1,000 product returneds
Rating
0.0
(0)
Developer
AgentToolWorks
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
8 minutes ago
Last modified
Categories
Share
What is this Shopify and WooCommerce scraper?
This Actor is a Shopify scraper and WooCommerce scraper in one, with a built-in price tracker. Paste the URLs of any Shopify or WooCommerce stores, mixed in one list, and get every product back in the same clean format: titles, prices, sale prices, variants, SKUs, barcodes (GTIN/UPC/EAN), stock, weights, options, images with their sizes and alt text, tags, categories and dates.
Turn on change tracking and schedule it, and it becomes a competitor price monitor: each run outputs only what changed since the previous one (price drops, price increases, back in stock, out of stock, new products, removed products).

What data can you extract from Shopify and WooCommerce stores?
One row per product, with its variants nested (or one row per variant, see Output). Every row has the same fields whichever platform the store runs on.
| Product data | Variant data | Store data |
|---|---|---|
| Title, handle, URL | Variant title and options (Size, Color) | Platform detected (Shopify or WooCommerce) |
| Vendor or brand, product type | SKU and barcode (GTIN, UPC, EAN) | Store domain and URL |
| Categories and tags | Price and compare-at (sale) price | Currency |
| Lowest and highest price, compare-at price, on sale | In stock, stock quantity where public | Collection or category read |
| Options with all their values | Backorder policy | Run summary per store |
| Images: URL, width, height, alt text, linked variants | Weight in grams | |
| Description as plain text and as HTML | Requires shipping, taxable | |
| Rating and review count (WooCommerce) | Variant image and position | |
| Created, updated and published dates | Created and updated dates (Shopify) |
Everything comes from the store's own public storefront: Shopify's products.json and Ajax product endpoints, and the public WooCommerce Store API. No login, no account, no customer data.
What can you use Shopify and WooCommerce product data for?
- Competitor price monitoring: track price changes and discounts across many stores, daily or hourly.
- Restock alerts: know when a sold-out product or size is back in stock.
- Product research and dropshipping: see what a brand sells, at what price, and what it launches.
- Price comparison and product feeds: match products across stores by barcode (GTIN) and build a feed.
- Catalog audits: missing SKUs or barcodes, out-of-stock share, sale depth, image alt text coverage.
- Data for AI agents and pipelines: one predictable JSON schema for any Shopify or WooCommerce store.
How to scrape a Shopify or WooCommerce store
- Click Try for free (or Start) on this page and sign in to Apify.
- Paste one or more store URLs in Store URLs: a home page (
https://www.allbirds.com), a Shopify collection (https://www.allbirds.com/collections/mens) or a WooCommerce category page. - Set Max products per store. You pay per product returned, so start small to look at the data.
- Turn on Include stock levels, barcodes and image alt text if you need them (Shopify; slower).
- Click Start. When the run finishes, open the Output tab, pick the Products or Variants view, and export as JSON, CSV, Excel or XML, or read it through the API.

Input
| Field | What it does |
|---|---|
storeUrls | Shopify or WooCommerce store URLs, mixed. A home page, a Shopify collection page or a WooCommerce category page. Up to 100 stores per run. |
maxProductsPerStore | Stop after this many products per store (default 1,000, up to 100,000). You pay per product returned. |
trackChanges | Save a snapshot per store and output what changed since the last run. |
outputProducts | Turn off to output only the changes (for scheduled monitoring). |
collection | A Shopify collection handle or WooCommerce category slug, for every store whose URL does not already name one. |
includeInventory | Shopify: read each product's public Ajax endpoint for stock counts, barcodes, backorder policy and image alt text. Slower: at most 500 products per store per run. |
includeDescription | Add description (plain text) and descriptionHtml (the store's HTML), plus shortDescription on WooCommerce. |
proxy | none (default) or datacenter (Apify Proxy) if a store rate-limits your runs. |
Example: one Shopify collection and one WooCommerce store, with barcodes and stock.
{"storeUrls": ["https://www.allbirds.com/collections/mens", "https://woocommerce.com"],"maxProductsPerStore": 500,"includeInventory": true}
Example: a daily price and stock monitor that outputs only changes.
{"storeUrls": ["https://competitor-one.com", "https://competitor-two.com"],"maxProductsPerStore": 20000,"trackChanges": true,"outputProducts": false}
Output
The dataset has three ready-made views in Apify Console and in the API:
- Products: one row per product.
- Variants (one row each): one row per variant, with SKU, barcode, price, stock and weight. The same as adding
unwind=variantsto the dataset API. - Changes: the change rows, when change tracking is on.


A Shopify product row from a real run (variants and images shortened):
{"rowType": "product","platform": "shopify","storeDomain": "www.allbirds.com","storeUrl": "https://www.allbirds.com","productId": "7340901859408","handle": "womens-allbirds-flip-flop-dusty-pink","title": "Women's Allbirds Flip Flop - Dusty Pink","url": "https://www.allbirds.com/products/womens-allbirds-flip-flop-dusty-pink","vendor": "Allbirds","productType": "Shoes","categories": [],"tags": ["allbirds::complete => true", "allbirds::edition => limited"],"price": 25,"priceMax": 25,"compareAtPrice": 50,"onSale": true,"currency": "USD","available": true,"requiresShipping": true,"sku": null,"inventoryQuantity": 13,"variantCount": 7,"options": [{ "name": "Size", "position": 1, "values": ["5", "6", "7", "8", "9", "10", "11"] }],"variants": [{"variantId": "42146889039952","variantTitle": "5","variantSku": "A12513W050","variantOptions": { "Size": "5" },"variantPrice": 25,"variantCompareAtPrice": 50,"variantAvailable": false,"variantInventory": 0,"variantAllowsBackorder": false,"variantBarcode": "196942293089","variantWeightGrams": 455,"variantRequiresShipping": true,"variantTaxable": true,"variantImage": null,"variantPosition": 1,"variantCreatedAt": "2026-03-27T14:03:50-07:00","variantUpdatedAt": "2026-09-30T17:03:07-07:00"}],"image": "https://cdn.shopify.com/s/files/1/1104/4168/files/A12513_26Q2_Allbirds-Flip-Flop-Dusty-Pink_PDP_LEFT.png?v=1774646345","images": ["https://cdn.shopify.com/s/files/1/1104/4168/files/A12513_26Q2_Allbirds-Flip-Flop-Dusty-Pink_PDP_LEFT.png?v=1774646345"],"imageDetails": [{"src": "https://cdn.shopify.com/s/files/1/1104/4168/files/A12513_26Q2_Allbirds-Flip-Flop-Dusty-Pink_PDP_LEFT.png?v=1774646345","alt": null,"width": 4000,"height": 4000,"position": 1,"variantIds": []}],"imageCount": 5,"rating": null,"reviewCount": null,"createdAt": "2026-03-27T14:03:50-07:00","updatedAt": "2026-09-30T17:03:07-07:00","publishedAt": "2026-09-25T16:58:13-07:00","collection": null,"scrapedAt": "2026-10-01T00:03:06.433Z"}
A WooCommerce product row has exactly the same fields. Where the WooCommerce Store API publishes nothing, the field is null rather than guessed: no creation or update dates, no barcodes, no shipping or tax flags. In exchange, WooCommerce rows carry rating and reviewCount.
{"rowType": "product","platform": "woocommerce","storeDomain": "woocommerce.com","productId": "18734006912442","title": "PH PostNord Shipping with Print Label","url": "https://woocommerce.com/products/ph-postnord-shipping-with-print-label/","categories": ["WooCommerce extensions", "Shipping, delivery and fulfillment", "Label printing"],"price": 99,"currency": "USD","available": true,"variantCount": 1,"imageCount": 5,"rating": null,"reviewCount": 0}
Prices are numbers in the row's currency (25 means 25.00), so they sort and chart directly. Weights are always grams, whatever unit the store uses.
Change rows
With trackChanges on, each run also outputs one row per change since the previous run. A real one: two sizes of a sneaker came back in stock at Kith between two runs 46 minutes apart.
{"rowType": "change","changeType": "back_in_stock","platform": "shopify","storeDomain": "kith.com","storeUrl": "https://kith.com","productId": "8286820892800","variantId": "45144949096576","title": "adidas x Entire Studios Adizero Adios 9 - Core Black / Feather Grey / Mist Stone","variantTitle": "7","handle": "aakj2303","url": "https://kith.com/products/aakj2303","price": 180,"oldPrice": null,"newPrice": null,"available": true,"currency": "USD","detectedAt": "2026-10-01T01:05:34.945Z","previousCheckAt": "2026-10-01T00:19:56.772Z"}
changeType is one of new_product, removed_product, price_up, price_down, back_in_stock, out_of_stock. Price changes fill oldPrice and newPrice (compared to the cent); stock changes leave them null and give the current price. A change on a single variant carries its variantId and variantTitle; a new or removed product has them null.
Run summary
The run's key-value store holds a SUMMARY record with the status of each store: ok, partial (stopped part way, with the reason; the products read are kept), blocked (the store refused the request: a bot challenge or an HTTP 403), unsupported (not Shopify, or WooCommerce with its Store API closed), refused (not a public https address) or failed. It also says whether a store had more products than your limit, so a cut catalog is never silent.
How to monitor competitor prices with a schedule
- Run the Actor once with Track changes since the last run on. This first run saves a baseline for each store and reports no changes.
- On the input page, click Save as a new task. Turn off Output product rows in the task if you only want the changes.
- Open Schedules, create a schedule (daily, or every few hours) and add the task to it.
- Every scheduled run outputs only what changed since the previous run. Add an integration (email, Slack, Google Sheets, a webhook, Make, Zapier or n8n) to be notified when a run has rows.
Snapshots are kept in your account's named key-value store storecatalog-state, one record per store and per collection or category. Delete a record to start that store over from a new baseline.
Two things worth knowing:
- Cover the whole catalog (
maxProductsPerStoreabove the store's size) to detect new and removed products. When a run stops at your limit, a product it did not reach may still exist, so the run reports only price and stock changes for that store and says so in the summary. - If a run stops at your spending limit before every change is delivered, that store's snapshot is not updated, so the next run reports those changes again instead of losing them.
How much does it cost to scrape a Shopify store?
Pay per event, no subscription, platform usage included:
| Event | Price |
|---|---|
| Product returned | $1.50 per 1,000 products ($0.0015 each) |
| Change detected | $0.005 per change |
| Run start | $0.00005 |
Examples:
- A 1,000 product store: $1.50.
- Apify's free plan includes $5 of monthly usage (apify.com/pricing), enough for about 3,300 products a month.
- A daily monitor of a 2,000 product store with Output product rows off pays only for changes: a day with 12 price or stock changes costs $0.06.
A run that finds nothing to output costs only the start fee. Set a maximum cost per run in the run options and the Actor stops cleanly when it is reached.
Use the Actor through the Apify API
Run it and get the products in one HTTP call (replace YOUR_APIFY_TOKEN, from Settings > API & Integrations in Apify Console):
curl -X POST "https://api.apify.com/v2/acts/agenttoolworks~shopify-woocommerce-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"storeUrls": ["https://www.allbirds.com"], "maxProductsPerStore": 100}'
Node.js, with the official apify-client:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('agenttoolworks/shopify-woocommerce-scraper').call({storeUrls: ['https://www.allbirds.com', 'https://woocommerce.com'],maxProductsPerStore: 100,includeInventory: true,});// One item per variant instead of per product: add { unwind: 'variants' }.const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items.map((p) => [p.title, p.price, p.currency]));
Python, with the official apify-client:
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("agenttoolworks/shopify-woocommerce-scraper").call(run_input={"storeUrls": ["https://www.allbirds.com"], "maxProductsPerStore": 100})for product in client.dataset(run["defaultDatasetId"]).iterate_items():print(product["title"], product["price"], product["currency"])
The API tab on this page has ready-made snippets for every language and endpoint.
FAQ
Does it work on every Shopify store?
On nearly every one: products.json is part of every Shopify storefront. A store behind an extra bot challenge is reported as blocked in the run summary.
Does it work on every WooCommerce store?
On WooCommerce stores whose Store API is open, which is the default in recent WooCommerce versions. Stores that close it are reported as unsupported, and stores behind a firewall as blocked.
How fast is it?
Measured on Apify: Allbirds (692 products, 3 catalog requests) in 3 seconds, the first 5,000 Kith products in 29 seconds. With Include stock levels, barcodes and image alt text, each product needs one more request, so plan about 1.5 minutes per 300 products (measured: 300 Allbirds products in 90 seconds). WooCommerce speed depends mostly on the store's server.
Can I get stock quantities and barcodes?
Shopify: turn on Include stock levels, barcodes and image alt text. Barcodes come back for every product that has one; stock counts only for stores that track inventory publicly. WooCommerce publishes a stock count only when stock is low, and never barcodes.
Can I get one row per variant, for a spreadsheet?
Yes: choose the Variants (one row each) view before exporting, or add unwind=variants to the dataset items API.
Can I scrape only one collection or category?
Yes: paste the collection URL (/collections/sale) or the WooCommerce category URL, or set Collection or category to apply the same one to every store.
Can I use it with Make, Zapier, n8n or Google Sheets?
Yes, through Apify's integrations: the Actor's dataset works with every Apify integration, and a webhook can fire when a run finishes.
Can AI agents use it through MCP?
Yes. Apify's hosted MCP server exposes Store Actors to MCP clients such as Claude or Cursor: https://mcp.apify.com?tools=agenttoolworks/shopify-woocommerce-scraper.
Is it legal to scrape Shopify and WooCommerce stores?
The Actor reads only the product information a store publishes to every visitor, through the storefront's public endpoints, without logging in, and it collects no personal data. As with any data, how you use it is your responsibility.
Something is missing or broken?
Open an issue in the Issues tab: we read every one, and fields asked for by users get added.
Other Actors by AgentToolWorks
- Job Scraper for Greenhouse, Lever, Ashby & Workable (JobsRadar): open roles from Greenhouse, Lever, Ashby, SmartRecruiters, Workable, Personio and Pinpoint, deduplicated into one list.
Learn more
- What this Shopify and WooCommerce scraper returns, platform by platform
- How to scrape a Shopify store: products.json, the Ajax API and their traps
Built by AgentToolWorks. Not affiliated with Shopify or with WooCommerce.