Shopify Products Scraper: Full Catalog Export
Pricing
from $0.60 / 1,000 products
Shopify Products Scraper: Full Catalog Export
Export full Shopify store catalogs: products, variants, SKUs, prices, compare-at prices, availability and image URLs. Gets past the 25,000-product limit and reports coverage per store.
Pricing
from $0.60 / 1,000 products
Rating
0.0
(0)
Developer
OpenFeeds
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
7 days ago
Last modified
Categories
Share
What does Shopify Products Scraper do?
Shopify Products Scraper exports the full public product catalog of Shopify stores to JSON, CSV or Excel: products, variants, SKUs, prices, compare-at prices, availability and image URLs, one clean row per product (or per variant).
You paste Shopify store URLs. For each Shopify store, the Actor reads the public products.json catalog feed that every Shopify storefront serves to shoppers and shopping agents, and returns every product it can reach. A store status record tells you, per store, how many products the catalog has and what coverage you got.
Think of it as a Shopify product export API alternative that works on any public Shopify store, without a login, an app install, a browser or a proxy.
It does not download images (URLs only), read stock quantities (Shopify's public feed only says in or out of stock), collect customer data or reviews, or get around any store's protection.
Why use Shopify Products Scraper?
- 🧱 Gets past Shopify's 25,000-product limit. The catalog feed stops at 25,000 products. For bigger Shopify stores the Actor also reads the feed in a second order and then collection by collection, removing duplicates. Example: for a store with about 35,000 products, the feed alone stops at 25,000; in our test the extra passes raised this to 32,792 products (93.6% coverage) in about 13 minutes.
- 📏 Coverage per store. Each store status compares the products found with the store's own product count, so you know whether you got the whole catalog.
- 💲 Priced per product, never per variant row. The flat one-row-per-variant sheet costs the same as the product layout.
- 🧾 Honest store status. Blocked, password-protected, headless or empty stores are reported in a separate
STORE_STATUSrecord and cost nothing. The dataset holds only products. - 🚫 No proxy needed. The Actor reads public storefront feeds at a polite pace, honours robots.txt and Shopify's rate limits, and never tries to get around a firewall.
- ⚙️ Apify platform extras: scheduling, API access, integrations (Make, Zapier, Google Sheets, Slack, webhooks), datasets in JSON/CSV/Excel/HTML, and use from AI agents through the Apify MCP server.
Use cases
- Assortment and price research: export competitors' Shopify catalogs and compare product types, vendors and price bands.
- Audit your own catalog: find products without SKUs, broken compare-at prices or missing images.
- Market mapping: how big is each Shopify store in a niche, which vendors and product types do they carry?
- BI, repricing and feed tools: a flat SKU and price sheet per Shopify store, refreshed on a schedule.
- AI agents: a stable, flat product schema that is cheap to fetch.
What data can you get from a Shopify store?
| Field | Example | Description |
|---|---|---|
storeDomain / storeName | www.deathwishcoffee.com / Death Wish Coffee | Shopify store host and name |
currency | USD | Store currency (ISO 4217) |
productId / handle | 7361969684535 / 2026-death-wish-coffee-mug | Shopify product id (as text) and URL slug |
title | 2026 Death Wish Coffee Mug | Product title |
vendor / productType | Deneen Pottery / Mugs | Brand label and product type set by the merchant |
tags | ["Merch", "Mug", "Sale"] | Product tags |
priceMin / priceMax | 30 / 30 | Lowest and highest variant price |
compareAtPriceMax / onSale | 38 / true | Highest compare-at ("was") price; any variant on sale |
available / availableVariantCount | true / 1 | In stock now, and how many variants are |
variants | [{ "sku": "UMDWYM26K", "price": 30, … }] | Every variant: SKU, options, price, compare-at price, availability, weight |
options | [{ "name": "Size", "values": ["S", "M"] }] | Option axes (Size, Color, …) |
imageUrl / imageUrls | https://cdn.shopify.com/…/mug.jpg | First image and all image URLs |
productUrl | https://www.deathwishcoffee.com/products/2026-death-wish-coffee-mug | Product page |
createdAt / updatedAt / publishedAt | 2025-10-24T11:04:05-04:00 | Dates as published (ISO 8601) |
descriptionText / descriptionHtml | Our 2026 mug… | Optional (Include product descriptions) |
sourceFeed / sourceUrl / scrapedAt | collections/all | Which feed page the product came from, and when |
Not included: stock quantities (Shopify's public feed only says in or out of stock), customer data, reviews.
How to scrape products from a Shopify store
- Open the Actor and paste one or more Shopify store URLs, one per line (
www.allbirds.com,https://www.tentree.com, or a collection URL such ashttps://www.tentree.com/collections/backpacks). - Set Max products per store. It is also your cost cap.
- Choose the output layout: one row per product (variants nested) or one row per variant (a flat sheet for Excel).
- Click Start.
- Download the products as JSON, CSV, Excel or HTML, or read them through the API. Open the
STORE_STATUSrecord (Storage → Key-value store) for each Shopify store's status and coverage.
How much does it cost to scrape a Shopify store?
The Actor uses pay-per-event pricing. You pay once per unique product written to the dataset, never per variant row:
| Apify plan | Price per product | Per 1,000 products |
|---|---|---|
| Free | $0.0009 | $0.90 |
| Starter | $0.0008 | $0.80 |
| Scale | $0.0007 | $0.70 |
| Business | $0.0006 | $0.60 |
Plus $0.00005 per run (the standard Actor start fee).
Examples on the Free plan:
- 3 Shopify stores × 20 products (the example input) = 60 products = $0.054.
- One store with 2,000 products = $1.80.
- A store with 30,000 products, with Max products per store raised to 30,000: the extra passes past Shopify's 25,000 limit usually reach about 94% of such a store, so about 28,000 products = about $25 (about $17 on Business). At the default of 10,000 products per store, the same store costs at most $9.
Not charged: variant rows, duplicate products found by more than one pass, products that could not be read, and blocked, empty, password-protected, rate-limited or skipped stores. The run stops cleanly at your maximum cost per run. If the run is moved to another server or you resurrect an aborted run, it continues where it stopped and never charges a product twice.
Input
See the Input tab for every option. The main fields:
- Shopify store URLs (
storeUrls): domains or URLs, one per line. A collection URL exports only that collection;*.myshopify.comdomains work too. Product page URLs (…/products/…) are skipped as invalid entries, because they would export the whole store. - Max products per store (
maxProductsPerStore, default 10,000): stops each store after this many products. - Output layout (
outputLayout):productsorvariants. - Include product descriptions (
includeDescriptions): adds the description as text and HTML; e-mail addresses and phone numbers are removed. - Get past the 25,000-product limit (
splitLargeStores, default on) and Extra requests per large store (splitRequestBudget, default 400) for very large stores.
Three Shopify stores, 20 products each:
{ "storeUrls": ["www.allbirds.com", "www.tentree.com", "www.deathwishcoffee.com"], "maxProductsPerStore": 20 }
One collection only:
{ "storeUrls": ["https://www.tentree.com/collections/backpacks"] }
A flat variant sheet (one row per variant, same price):
{ "storeUrls": ["www.deathwishcoffee.com"], "outputLayout": "variants" }
Output
You can download the dataset in various formats such as JSON, HTML, CSV or Excel. The Overview view shows the key product fields; the Variants (flat) view unwinds every product into one row per variant, at no extra cost.
One product (layout products, real output, image list shortened):
{"storeDomain": "www.deathwishcoffee.com","storeName": "Death Wish Coffee","currency": "USD","productId": "7361969684535","handle": "2026-death-wish-coffee-mug","title": "2026 Death Wish Coffee Mug","vendor": "Deneen Pottery","productType": "Mugs","tags": ["HCM", "Merch", "Mug", "Sale"],"productUrl": "https://www.deathwishcoffee.com/products/2026-death-wish-coffee-mug","priceMin": 30,"priceMax": 30,"compareAtPriceMax": 38,"onSale": true,"available": true,"variantCount": 1,"availableVariantCount": 1,"options": [{ "name": "Title", "values": ["Default Title"] }],"variants": [{"variantId": "41956717559863","variantTitle": "Default Title","sku": "UMDWYM26K","option1": "Default Title","option2": null,"option3": null,"price": 30,"compareAtPrice": 38,"variantAvailable": true,"grams": 794,"requiresShipping": true,"taxable": true,"position": 1,"variantImageUrl": null,"variantUrl": "https://www.deathwishcoffee.com/products/2026-death-wish-coffee-mug?variant=41956717559863"}],"imageUrl": "https://cdn.shopify.com/s/files/1/0271/7209/files/DeathWishCoffee_December2025_Product_Mug_Front_Web.jpg?v=1767879839","imageUrls": ["https://cdn.shopify.com/s/files/1/0271/7209/files/DeathWishCoffee_December2025_Product_Mug_Front_Web.jpg?v=1767879839","…"],"imageCount": 8,"descriptionText": null,"descriptionHtml": null,"createdAt": "2025-10-24T11:04:05-04:00","updatedAt": "2026-10-13T00:32:58-04:00","publishedAt": "2025-12-31T08:49:09-05:00","sourceFeed": "collections/all","sourceUrl": "https://www.deathwishcoffee.com/collections/all/products.json?limit=20&page=1","scrapedAt": "2026-10-13T04:32:58.775Z"}
One row in layout variants (shortened): the product fields without variants and options, plus the variant columns.
{"storeDomain": "www.deathwishcoffee.com","currency": "USD","productId": "7225649561655","title": "Signature Standard Tee","variantId": "41473922695223","variantTitle": "S","sku": "UTCLBF02","option1": "S","price": 15,"compareAtPrice": 30,"variantAvailable": true,"grams": 160,"variantUrl": "https://www.deathwishcoffee.com/products/signature-standard-tee?variant=41473922695223","vendor": "Sportiqe","productType": "Apparel","priceMin": 15,"priceMax": 15,"onSale": true,"variantCount": 6,"availableVariantCount": 4}
One Shopify store in the STORE_STATUS record (shortened):
{"input": "www.deathwishcoffee.com","storeDomain": "www.deathwishcoffee.com","status": "OK","message": "145 products; coverage 100% of 145.","storeName": "Death Wish Coffee","currency": "USD","catalogSize": 145,"catalogSizeSource": "meta","productsFound": 145,"productsPushed": 145,"coveragePct": 100,"limitReached": false,"capReached": false,"splitUsed": false,"requests": 3,"durationMs": 1472}
Store status codes explained
| Status | What it means | Charged? |
|---|---|---|
OK | All products read, or Max products per store reached (limitReached: true) | per product |
EMPTY | The store or collection has no products in its public feed | no |
NOT_SHOPIFY | No Shopify catalog feed and no Shopify signs: probably not a Shopify store | no |
NO_PUBLIC_FEED | A Shopify store whose public feed is switched off (usually a headless storefront) | no |
PASSWORD_PROTECTED | The store is behind a password page | no |
BLOCKED | The store's own firewall blocked the request. We skip it and never try to get around protection | no |
RATE_LIMITED | Shopify kept answering "too many requests" after the Actor paused and slowed down. Products already exported are kept; run the store again later | only products already delivered |
ROBOTS_DISALLOWED | The store's robots.txt disallows the feed, or asks for a crawl delay over 30 s | no |
UNREACHABLE | DNS, TLS or connection failure on both the www. and the bare domain | no |
ERROR | Server errors, timeouts or broken JSON after two retries, or a feed whose products could not be read | only products already delivered |
DUPLICATE | Same Shopify store as an earlier entry (for example two domains of one store) | no |
INVALID_INPUT | The entry is not a domain or URL, or it is a product page URL | no |
STOPPED | The run stopped first (maximum cost reached or run aborted) | only products already delivered |
A run with no products succeeds when every store gave a store-side answer (blocked, empty, not Shopify, and so on), and fails only when stores could not be read because of errors or invalid input.
Tips
- Max products per store doubles as a cost cap: 1,000 means at most $0.90 per store on the Free plan.
- Collection URLs export a slice of a Shopify store, for example one category.
- For a flat sheet, use layout
variants, or keep layoutproductsand open the Variants (flat) view or export. - Large stores take minutes, not seconds. The Actor reads each store one request at a time, 0.3 to 0.5 s apart (0.4 s on average), three stores in parallel. A page holds up to 250 products, so a 25,000-product store takes about two minutes; a 35,000-product store with all extra passes took about 13 minutes in our test.
- Schedule it (daily or weekly) to keep a fresh catalog snapshot; compare the datasets to spot new products and price changes.
FAQ
Is it legal to scrape Shopify stores?
The Actor reads only public product and price data that Shopify stores publish for shoppers. It uses no login, gets around no protection, and checks each store's robots.txt first. You are responsible for your own contracts and for how you use the data. If you are a Shopify merchant, section 1 of Shopify's Terms of Service forbids monitoring the Services with scrapers or other automated means. Individual stores' terms may also apply. This Actor is not affiliated with Shopify.
Our Actors are ethical and do not extract any private user data, such as email addresses, gender, or location. They only extract what the user has chosen to share publicly. We therefore believe that our Actors, when used for ethical purposes by Apify users, are safe. However, you should be aware that your results could contain personal data. Personal data is protected by the GDPR in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.
Which endpoint does it read?
/collections/all/products.json, the collection JSON feed that Shopify storefronts list in their own /agents.md, with /products.json as the fallback and second order. Store name, currency and product count come from /meta.json. Each store's robots.txt is checked first; Shopify's default robots.txt has no rule against these paths. The Actor never calls per-product endpoints.
Why was a Shopify store BLOCKED or skipped?
Some stores run their own firewall in front of Shopify, and headless storefronts switch the public feed off. The Actor skips them and reports why. It never tries to get around protection: no proxies, no CAPTCHA solving.
Why RATE_LIMITED?
Shopify limits how fast one client can read storefront feeds. When it answers "too many requests", the Actor pauses every store and waits: the time Shopify asks for (if it asks for more than 60 s, the store stops at once), or 30 s for Shopify's usual rate-limit page, or 10 s otherwise. Then it slows that store down and retries the request once. A store gets up to 5 such waits. If Shopify keeps refusing, the store ends RATE_LIMITED with the products already exported kept. Run that store again later.
Why did I get fewer products than the store shows?
Hidden, draft, wholesale or sales-channel-limited products are not in the public feed. Very large stores are limited by Shopify's 25,000-product feed limit; the extra passes recover most, but not always all, of the rest. coveragePct in the store status shows how complete each export is.
Does it convert currencies or give stock quantities?
No. Prices are in the store's own currency (currency), as the store publishes them. Shopify's public feed has no stock quantities, only whether a variant is available.
Does it download images?
No, it returns image URLs only.
Can it monitor price changes?
Schedule the Actor and compare the datasets of two runs. A built-in "changes only" option is planned.
Do I need a proxy?
No. There is deliberately no proxy option: the Actor reads public feeds directly and skips stores that block automated access instead of trying to evade them.
Support
Found a bug or need a field? Open an issue in the Issues tab. To run the Actor from your own code, see the API tab, for example:
curl -X POST "https://api.apify.com/v2/acts/openfeeds~shopify-store-products-scraper/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \-H "Content-Type: application/json" \-d '{"storeUrls":["www.deathwishcoffee.com"],"maxProductsPerStore":50}'
Changelog
- 1.0 (2026-10-13): First release: full catalog export from Shopify stores, product and variant layouts, 25,000-limit split with coverage per store, store status record, pay per product.