StoreShelf Product & Price Scraper for WooCommerce®
Pricing
from $0.70 / 1,000 results
StoreShelf Product & Price Scraper for WooCommerce®
[From $1.00/1K, no usage fees] Export products from WooCommerce and Shopify stores in one schema: SKUs, prices, discounts, stock status, and variants on Shopify. Shopify is best effort: it can refuse reads; a refused store is not charged. CSV or JSON, no login. Not affiliated with either company.
Pricing
from $0.70 / 1,000 results
Rating
0.0
(0)
Developer
Vladimir Tsaplin
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
19 hours ago
Last modified
Categories
Share
StoreShelf scrapes products from WooCommerce stores in one schema: SKUs, prices, discounts and stock status. Use it to watch competitor prices and assortment. Paste store URLs and get CSV or JSON, with no login. WooCommerce is the main path. Shopify stores are read too: a run on Apify's cloud read two of them, and reads stay best effort, as How Shopify stores are read explains. Some stores of either kind block cloud servers, see Limits.
StoreShelf is an independent product. It is not affiliated with, endorsed by or sponsored by WooCommerce, Automattic, Shopify or any store named on this page. The names only say which systems the Actor can read. WooCommerce and its associated designs are trademarks of Automattic Inc. Shopify is a trademark of Shopify Inc.
Sample record from a real run on a WooCommerce store on 2026-10-31:
{"platform": "woocommerce","store_domain": "mandarinstone.com","title": "Dijon Heritage Limestone Pentagon","sku": null,"price_min": 7.08,"price_max": 7.08,"compare_at_price": 9.44,"discount_pct": 25.0,"currency": "GBP","in_stock": true,"variants_count": 1,"product_url": "https://www.mandarinstone.com/product/dijon-heritage-limestone-pentagon/"}
What you get
| Field | Example | Notes |
|---|---|---|
title | Dijon Heritage Limestone Pentagon | As published |
price_min | 7.08 | Lowest variant price. A price of 0 counts as no price, so it is null on a WooCommerce product whose lowest price is 0, see Limits |
compare_at_price | 9.44 | Original price of the deepest discount. Null when nothing is discounted, and null with discount_pct on a WooCommerce product whose lowest price is 0 |
discount_pct | 25.0 | Calculated from price and original price |
currency | GBP | Store currency, null when the store does not publish it |
in_stock | true | True when any variant is available, null when the store does not say |
variants | List | ID, title, SKU, price, original price and availability of each variant |
sku | null | First variant with a SKU, null when the product list shows none. On the store in this sample, 8 of the 1,000 products we read had one |
product_url | Link | Public product page |
description | Plain text | As published, with email addresses and phone numbers removed |
The WooCommerce Store API product list gives only a price range for a variable product, and the Actor does not request each variation, so these products show their price range and variant count with an empty variants list. Vendor exists on Shopify and in schema.org data, dates on Shopify only.
How much does it cost to scrape a WooCommerce store?
You pay per product in the output, with no usage fees.
| Apify plan | Price per 1,000 products | Store with 500 products |
|---|---|---|
| Free | $1.00 | $0.50 |
| Starter (Bronze) | $0.90 | $0.45 |
| Scale (Silver) | $0.85 | $0.43 |
| Business (Gold) | $0.70 | $0.35 |
A run also carries Apify's small start fee of $0.00005 per run for each GB of memory. Set Maximum products in total to cap a run. Stores that fail are not charged.
How to run it
- Paste store URLs. WooCommerce or Shopify is detected for you.
- Add a search term or In-stock products only if you want, then press Start.
- Download the results as CSV, JSON or Excel from the Output tab.
To track prices, save the input as a task, add a schedule and compare the runs.
How Shopify stores are read
On 2026-10-31 one run on Apify's cloud read real products from two Shopify stores, so Shopify reads do work from there. They stay best effort: that is one run on two stores, and it is no promise for any other store or any later run. The prefilled input and the Task Examples use a WooCommerce store for this reason.
- The Actor does not sign its requests. Shopify's changelog says bots that do not sign with Web Bot Auth get its strictest rate limits, and the
/agents.mdpage each Shopify store publishes says server-to-server clients must use Web Bot Auth. The Actor identifies itself by name. It uses no proxies and no browser identity to get around a limit. - What a refusal looks like.
/products.jsonanswers HTTP 429 withRetry-After: 60, while the rest of the store keeps answering. The Actor waits as asked, for up to 65 seconds, and tries twice more. It then reports that store asHTTP_429inRUN_SUMMARYand charges nothing for it. Those waits can take about two minutes per store. - What we measured away from Apify. On 2026-10-31, from one address outside Apify, three runs in a row read nothing from the first Shopify store we tried. A later run from the same address read 100 products from that store. The next Shopify run read 50 from a second store and was refused by the first. One later run of 5 products per store read one store and was refused by the other. So the limit comes and goes, and one good run promises nothing about the next.
- Every release is checked from Apify's cloud. A release runs the Actor 3 times on two Shopify stores, and the Store description says "Export products from WooCommerce and Shopify stores" only if every run reads both stores. If it says "Export products from WooCommerce stores", that check did not pass for this build, so do not plan on Shopify reads. The check reads 5 products per store, so even when it passes, a full Shopify catalog stays best effort.
If you do read Shopify stores, run them again later when refused, and expect to read fewer at a time than WooCommerce stores.
Limits
- Up to 1,000 products per store, and two stores at a time.
- A search term or In-stock products only reads the catalog page by page and filters it in the Actor, the same way on WooCommerce and Shopify. The store's own search is not used, so a search covers the title, vendor, type, SKU, handle and tags, and not the description.
- A filtered scan stops at 40 catalog pages per store: 4,000 products on WooCommerce, 10,000 on Shopify. If a catalog is larger, matches can be missing. You keep what was found, and the store is named in
not_processed_targetsandcut_scansinRUN_SUMMARY. A run that stored nothing from such a scan fails, because "no match" would not be proven. - The Actor reads each store's robots.txt first. It does not request a path the store disallows, and it keeps the store's Crawl-delay, retries included, so a store that asks for 10 seconds between requests reads slowly.
- A price of 0 is read as no price. Stores sometimes list internal items at $0, such as checkout helpers, and they stay in the catalog with null
price_minandprice_max. A WooCommerce variable product with a free variation, such as a free sample, also gets a nullprice_min, but next to a realprice_max, and itscompare_at_priceanddiscount_pctare null too. The Store API product list gives only a price range for a variable product, and the Actor does not request each variation, so it cannot skip the free one. A nullprice_mintherefore does not always mean an internal item: checkprice_max. On the store in the prefilled input, which offers free samples, 544 of the 1,000 products we read had a nullprice_min, and all 1,000 had aprice_max. On Shopify a $0 variant is skipped, and the lowest other variant price is used. - A store that closes its catalog, as some large brands do, cannot be read. If the page has schema.org product data, you get those products; otherwise the store is reported as failed. Such data can give a price range with no variant count, and
variants_countis then null. - Some stores block cloud servers. A store can open fine from a home address and still answer HTTP 403 to Apify's servers, as two WooCommerce stores did in a test on 2026-10-31. Such a store fails with
CATALOG_NOT_PUBLICand no product is charged. The Actor uses no proxies and no browser identity to get past a block, so no setting changes this.
FAQ
Which stores work? WooCommerce stores with the Store API on, and Shopify stores that serve /products.json when Shopify does not refuse the read. Either way the store has to let Apify's servers in: a store you can open in your browser can still block them. Start with a small run to see whether a store works.
Is scraping store catalogs legal? The Actor reads public catalog data that stores serve without login, and it follows each store's robots.txt. Check the terms of the stores you monitor and use the data in line with the law that applies to you. Shopify's own terms also restrict access to its services by automated means, and its stores ask server-to-server clients to sign requests with Web Bot Auth, which this Actor does not do. Whether that binds you is a question for your legal adviser.
The result is empty. What now? Open RUN_SUMMARY in the run's key-value store. It names each failed store and the reason: for example CATALOG_NOT_PUBLIC, ROBOTS_DISALLOWED or HTTP_429. CATALOG_NOT_PUBLIC with the message homepage answered HTTP 403 usually means the store blocks cloud servers. No product was charged. not_processed_targets names the stores a run did not finish, for example because it reached Maximum products in total or the page limit of a filtered scan.
Does it collect store emails or contacts? No. The output has no contact field. When a store writes an email address or phone number into a product description, the Actor replaces it with [email removed] or [phone removed]. This goes by pattern, so an address spelled out in words or a short local number can stay, and a part number shaped like a phone number can go. Other description text stays as the store wrote it, including any names or street addresses.
Call it from your own code
curl -X POST "https://api.apify.com/v2/acts/creatortsv~storeshelf-product-price-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"storeUrls": ["https://www.mandarinstone.com"], "maxItemsPerStore": 100}'
Scope
What's Included: public catalogs of WooCommerce stores, best-effort reads of public Shopify catalogs, prices, discounts from regular and compare-at prices, stock status, per-store failure report.
What's Not Included: guaranteed Shopify reads, Web Bot Auth signing, store discovery, contact fields, order or sales volumes, stock quantities, password-protected stores, stores that block Apify's servers, proxy rotation, and other store platforms unless the page carries schema.org product data.
Keywords: scraper for WooCommerce stores, export products from a WooCommerce store, WooCommerce Store API, price monitoring for WooCommerce stores, competitor price monitoring, ecommerce product data.