Shopify Store Scraper & Products API — Prices & Variants
Pricing
$0.50 / 1,000 products
Shopify Store Scraper & Products API — Prices & Variants
Full product catalogue of any Shopify store from its public products.json: title, vendor, type, tags, variants with price, SKU and stock, images, collections. Unofficial Shopify API.
Pricing
$0.50 / 1,000 products
Rating
0.0
(0)
Developer
yestrue
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
The full product catalogue of any Shopify store as clean JSON records, straight from the public products.json every Shopify storefront serves without a key: title, vendor, product type, tags, dates, price range and currency, every variant with its price, compare-at price, SKU, options and availability, images, description as plain text, product URL. Read the whole store or just the collections you name, list the store's collections, filter by stock, price or vendor — and find out in one record whether a site is a Shopify store at all.
Try it in 1 minute:
- Press Start — the prefilled input reads the first 250 products of allbirds.com.
- Seconds later the Output tab shows one record per product with vendor, type, tags, price range in USD, variants with sizes and stock, images and the description.
- Download JSON, CSV or Excel, or add more Store URLs, name Collections, raise Max products per store and switch the filters on.
Price: $0.50 per 1,000 products (one product = one record with all its variants and images). Stores that are not Shopify, blocked stores, empty stores and collections, unknown collections, invalid inputs and the optional collection list are free.
Use it to:
- Monitor competitors' catalogues on a schedule: new products, price and compare-at changes, what went out of stock — per variant.
- Build a price-comparison or market-research dataset across dozens of Shopify brands in one run.
- Feed a dropshipping, affiliate or AI product-recommendation pipeline with structured products, options and images.
- Audit your own store or a client's: missing SKUs, products without images, empty descriptions, unpublished items.
- Check in one go which of 500 domains run Shopify and how many products each one lists (
NOT_SHOPIFYis free).
How it works
- Store URLs are reduced to their origin (
allbirds.com,https://www.allbirds.com/products/x→https://www.allbirds.com). Unless you switch it off, the store'srobots.txtis read first and a store that disallows/products.jsongets a freeROBOTS_DISALLOWEDrecord (Shopify's default allows it). - Detection:
<store>/products.json?limit=1must answer JSON with aproductsarray. If it does not, the homepage is checked for the markers every Shopify theme has (cdn.shopify.com,Shopify.theme,shopify-section): no markers → one freeNOT_SHOPIFYrecord; markers but no catalogue (HTTP 403/404, a password page, HTML instead of JSON) → one freeFAILEDrecord that says so. - Currency:
products.jsoncarries none, so it is read once per store from<store>/meta.json(which also names the store) or the homepage'sShopify.currencymarker;nullwhen the store says neither. - Products:
<store>/products.json?limit=250&page=n— or<store>/collections/<handle>/products.json?…for each named collection — page after page, with Delay between pages in between, until the page comes back short, Max products per store is reached, or 200 pages (50,000 products). A product listed in several collections is delivered once, under the first collection it appeared in. Products that fail the in stock / price / vendor filters are not delivered and not charged. - Collections (optional):
<store>/collections.json→ one free record per collection with id, handle, title, product count and dates, statusCOLLECTION.
Requests go directly to the store (no proxy unless a connection drops, or Proxy from the first request is on). A store that throttles (HTTP 429) is waited out on the same IP for up to 90 seconds; a store that refuses a request (HTTP 403, a bot check) is never retried from another IP. The record says what happened.
Input
| Field | What it does |
|---|---|
storeUrls | Stores to read: a domain or any URL on the store, one per line. |
collections | Optional. Collection handles (mens) or collection URLs, one per line; a handle applies to every store, a URL to its own store. |
maxProducts | Products to deliver per store after filters, up to 50,000 (default 250 = one page). |
includeCollectionsList | Also list the store's collections as free COLLECTION records (default off). |
onlyAvailable | Keep only products with at least one variant in stock. |
minPrice, maxPrice | Keep products with at least one variant priced in the range (store currency). |
vendor | Keep only this vendor (case-insensitive). |
includeDescription | Plain-text description, HTML removed, contacts scrubbed, cut at 5,000 characters (default on). |
includeDescriptionHtml | Also the original body_html (default off). |
maxConcurrency | Stores read in parallel (default 3); pages within a store are sequential. |
delayMs | Pause between two pages of the same store (default 500 ms). |
respectRobots | Skip stores whose robots.txt disallows /products.json (default on). |
proxyFromFirstRequest | Send every request through the proxy from the first try (default off: the first try is direct). |
proxyConfiguration | The proxy for retries after a network error — or for every request with the switch above on. |
Output
One record per product:
| Field | What it is |
|---|---|
productId, handle, title, url | Identity and product page |
vendor, productType, tags[] | How the store classifies it |
createdAt, publishedAt, updatedAt | ISO 8601 dates (publishedAt null when unpublished) |
priceMin, priceMax, currency, available | Price range as numbers, currency from the store's meta/homepage, any variant in stock |
variants[] | { id, title, sku, price, compareAtPrice, available, options { Color, Size … }, grams, requiresShipping } |
options[] | { name, values[] } — the product's option names and values |
images[], imageCount | { src, alt, width, height }, featured image first |
description, descriptionHtml | Plain text (phones and e-mails removed, max 5,000 chars) and, on request, the original HTML |
store, collection, position | The store's origin, the collection handle it was read from (or null), 1-based position in the store's listing |
input, status, error, scrapedAt | What you gave, OK / NOT_SHOPIFY / FAILED / NO_RESULTS / NOT_FOUND / ROBOTS_DISALLOWED / INVALID_INPUT / COLLECTION, the reason, and when |
A COLLECTION record (with Include the collection list on) has collection, collectionId, title, productsCount, publishedAt, updatedAt, url.
Example
{"input": "https://www.allbirds.com","store": "https://www.allbirds.com","productId": "7340901859408","handle": "womens-tree-runner-natural-white","title": "Women's Tree Runner - Natural White","vendor": "Allbirds","productType": "Shoes","tags": ["womens", "tree", "runner"],"createdAt": "2026-03-27T21:03:50.000Z","publishedAt": "2026-09-25T23:58:13.000Z","updatedAt": "2026-10-19T18:19:16.000Z","url": "https://www.allbirds.com/products/womens-tree-runner-natural-white","priceMin": 98,"priceMax": 98,"currency": "USD","available": true,"variants": [{ "id": "42146889039952", "title": "7", "sku": "TR1W070", "price": 98, "compareAtPrice": null, "available": true, "options": { "Size": "7" }, "grams": 455, "requiresShipping": true },{ "id": "42146889072720", "title": "8", "sku": "TR1W080", "price": 98, "compareAtPrice": null, "available": false, "options": { "Size": "8" }, "grams": 460, "requiresShipping": true }],"options": [{ "name": "Size", "values": ["7", "8"] }],"images": [{ "src": "https://cdn.shopify.com/s/files/1/1104/4168/files/TR1W_PDP_LEFT.png?v=1774646345", "alt": null, "width": 4000, "height": 4000 }],"imageCount": 1,"description": "Light, breathable and machine-washable. Made with eucalyptus tree fiber.","descriptionHtml": null,"collection": null,"position": 1,"status": "OK","error": null,"scrapedAt": "2026-10-19T12:00:00.000Z"}
FAQ
Is this an official API? No, it's an unofficial API built on public pages and endpoints — the products.json, collections.json and meta.json files every Shopify storefront serves to any visitor, with no key and no login. The data is what the store itself publishes; this Actor only shapes it into stable JSON records.
Does it work on WooCommerce, Magento or other platforms? No — this version is Shopify only. A site that is not a Shopify store gets one free NOT_SHOPIFY record, which makes the Actor a cheap way to check which of your domains run Shopify.
Why is a store FAILED? Some stores disable /products.json, sit behind a Cloudflare bot check, or are password-protected (pre-launch). The record says which. A store that throttles direct requests (HTTP 429) is waited out for up to 90 seconds on the same IP; if it keeps refusing, run again with Proxy from the first request on, ideally with a residential proxy group. A refused request is never retried from another IP mid-run: there is no bypass, by design.
Where do the currency and inventory counts come from? products.json has neither. The currency is read once per store from meta.json or the homepage marker (most stores have one; otherwise null). Stock is the per-variant available flag — exact inventory quantities and barcodes are not public.
How are collections handled? Name handles or collection URLs and only those are read; each product carries collection. A product in several of your collections is delivered once, under the first. With Include the collection list on, every collection of the store is one free record with its product count, so you can pick handles for the next run.
Like it? A short review on the Store page helps other people find this Actor. Something missing or broken? Tell us on the Issues tab — we read every one.
Related Actors
- Website Tech Stack Detector — CMS, frameworks and analytics of any site
- Sitemap Extractor — every URL, date and image from a site's sitemaps
- Web Fetch API — any URL as HTML, text, Markdown or JSON
- Website Screenshot API — full page and mobile screenshots
- Article Extractor API — title, author, date and full text of any article