Shopify Scraper: Products, Prices & Variants API avatar

Shopify Scraper: Products, Prices & Variants API

Pricing

from $0.72 / 1,000 products

Go to Apify Store
Shopify Scraper: Products, Prices & Variants API

Shopify Scraper: Products, Prices & Variants API

Scrape every product from any Shopify store's products.json: prices, compare-at prices, variants, SKUs, stock, images. Bulk stores, CSV/Excel/JSON.

Pricing

from $0.72 / 1,000 products

Rating

0.0

(0)

Developer

shawn slam

shawn slam

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

21 hours ago

Last modified

Share

Get every public product, price, variant and stock flag from any Shopify store as JSON, CSV or Excel. $0.90 per 1,000 products, no login, no browser.

Point it at one store or a thousand. It reads each store's own public product feed, adds the store's currency, and hands you one clean row per product (or per variant if you want size/colour rows for a spreadsheet).

Quick start

  1. Press Start. The form is already filled with this example input, so the first run returns real rows in under a minute:
{
"stores": [
"allbirds.com",
"kith.com"
],
"maxProductsPerStore": 50
}
  1. Swap in your own values, or call the Actor through the Apify API, Make, Zapier, n8n or the Python/JS clients with the same JSON.
  2. Download the results as JSON, CSV or Excel from the Output tab, or schedule the run to repeat.

Output fields

Every row has: store, productId, handle, title, url, vendor, productType, tags, currency, priceMin, priceMax, compareAtPriceMax, onSale, available, variantCount, options, imageUrl, imageCount, createdAt, updatedAt, publishedAt, scrapedAt, optional description, and a variants list (id, title, sku, price, compareAtPrice, available, option1-3, grams). In variant mode each variant becomes its own row with variantId, variantTitle, sku, price, compareAtPrice, variantAvailable, option1-3 and weightGrams as flat columns.

The full guide below is also published as "How to Scrape Shopify Products, Prices and Stock (products.json to CSV)".

What the Shopify products.json feed gives you

Every Shopify storefront answers GET /products.json, unless the merchant has turned it off with an app or a custom proxy. The response is a list of products. Each product has:

  • the product ID, handle (the URL slug), title, vendor, product type and tags
  • created, updated and published timestamps
  • a list of variants: each size or colour combination with its own ID, SKU, price, compare-at price (the "was" price), weight and an available flag
  • option names and values (for example Size: 8, 8.5, 9...)
  • image URLs
  • the description as HTML (body_html)

What it does not give you:

  • Stock quantity. Shopify only exposes a yes/no available flag publicly. Exact inventory counts are private to the merchant.
  • Currency. Prices are plain numbers in the store's base currency. The currency code lives in a separate file, /meta.json.
  • Reviews, sales counts or traffic. None of that is in the feed.

There are also two limits that trip up almost everyone who writes their own script:

  1. Page size. The feed returns at most 250 products per request (?limit=250). You have to page with &page=2, &page=3 and so on.
  2. The 25,000 cap. Shopify refuses requests where page × limit goes past 25,000 (you get HTTP 400). For stores with more than 25,000 products you need to fetch collection by collection (/collections/{handle}/products.json) instead.

A third, less known issue: some stores return a page with fewer than 250 products before the real end of the catalog. A script that stops at the first short page silently loses products. The Actor keeps paging until it gets an empty page, and skips any product ID it has already seen, so a store that ignores the page parameter can never make you pay for duplicates.

How to scrape Shopify products, step by step

Step 1: Open the Actor and list your stores

Open Shopify Scraper: Products, Prices & Variants API and press Try for free. You need a free Apify account; the free plan includes monthly platform credit, which covers thousands of products.

In Stores, paste one store per line. Any of these forms work:

  • allbirds.com
  • https://kith.com
  • any page URL from the store, such as a product or collection link (only the domain is used; set Collection to filter)

You can add hundreds of stores in one run. Each store is paged on its own, politely: at most a few requests at a time and about one request every 2 seconds per store.

Step 2: Choose product rows or variant rows

Output mode decides the shape of your table:

  • product (default): one row per product, with priceMin, priceMax, onSale, available, variantCount and the full variants list nested inside. Best for catalog overviews and price monitoring.
  • variant: one row per size/colour, with sku, price, compareAtPrice, variantAvailable, option1–option3 and weightGrams as flat columns. Best for spreadsheets, SKU matching and size-level stock checks.

Variant mode produces many more rows. In our test run below, 3 products became 42 rows, because each shoe came in 14 sizes. You pay per row, so pick the mode you actually need.

Step 3: Limit the run (optional)

  • Collection: a collection handle such as mens or sale fetches only that collection. This is also how you get past the 25,000-product cap on huge stores: run once per collection.
  • Max products per store: the default is 1,000. Set 0 to take the whole catalog.
  • Max results: a hard cap across all stores. The run stops cleanly when it is reached and you are never charged past it.
  • Include description: adds the product description as plain text (HTML stripped, cut at 2,000 characters). Leave it off if you only need prices; it keeps the dataset small.

Step 4: Run it and download the data

Press Start. A run over two stores takes a few seconds. When it finishes, open the Output tab and export as CSV, Excel, JSON, XML or HTML, or fetch the dataset through the Apify API.

Every run also writes a RUN_SUMMARY record to its key-value store: how many products came from each store, and a plain-English reason for any store that failed ("Not a Shopify store, or its public product feed is turned off"). Failed stores cost nothing.

Step 5: Automate it

To track prices over time, save your input as a Task and add a Schedule (daily, hourly, any cron). Each run gets a fresh dataset. To get rows into Google Sheets, Make, Zapier or n8n, use the Apify integration for that tool: "Run Actor", then "Get dataset items". From code, the Apify Python and JavaScript clients take the same JSON input:

from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("mrslm_data/shopify-products").call(run_input={
"stores": ["allbirds.com", "kith.com"],
"maxProductsPerStore": 50,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["store"], item["title"], item["priceMin"], item["currency"])

Real example 1: two stores, product mode

This is the Actor's default input, the same thing you get when you press Start without changing anything:

{
"stores": ["allbirds.com", "kith.com"],
"maxProductsPerStore": 50
}

Result from a real run on 28 October 2026: 100 products in 5.6 seconds (50 per store), and 100 product charges, so the cost was $0.09 plus the $0.00005 start fee. A few rows, trimmed to the main columns:

storetitlevendorproductTypepriceMincompareAtPriceMaxonSaleavailablevariantCount
allbirds.comWomen's Allbirds Flip Flop - Dusty PinkAllbirdsShoes50nullfalsetrue7
allbirds.comWomen's Tree Dasher Relay - Blizzard/Hazy Cobalt (Clarity Blue Sole)AllbirdsShoes67135truefalse13
allbirds.comWomen's Wool Runner Mizzle - Natural Grey (Cream Sole)AllbirdsShoes62125truetrue7
kith.comSalomon XT-Whisper GORE-TEX - Iron / Shadow Gray / Black OliveSalomonLow Top Sneakers165nullfalsetrue30
kith.comRick Owens Geobaskets - Black / MilkRick OwensBoots840nullfalsetrue18

Already useful at a glance: 13 of the 50 Allbirds products were on sale (a compare-at price above the current price), 47 were in stock in at least one size, and those 100 products held 1,284 variants between them. Kith's prices in the sample ran from $65 to $1,650, with nothing marked down.

Real example 2: one collection, variant mode

{
"stores": ["allbirds.com"],
"collection": "mens",
"outputMode": "variant",
"maxProductsPerStore": 3
}

Result: 3 products became 42 variant rows in 4.5 seconds, with 42 product charges. One row:

{
"store": "allbirds.com",
"productId": 7199602016336,
"handle": "mens-wool-cruiser",
"title": "Men's Wool Cruiser - Natural Grey (Natural White Sole)",
"url": "https://allbirds.com/products/mens-wool-cruiser",
"vendor": "Allbirds",
"productType": "Shoes",
"currency": "USD",
"priceMin": 105,
"priceMax": 105,
"onSale": false,
"available": true,
"variantCount": 14,
"variantId": 41243415609424,
"variantTitle": "8",
"sku": "A11723M080",
"price": 105,
"compareAtPrice": null,
"variantAvailable": true,
"option1": "8",
"weightGrams": 685,
"updatedAt": "2026-10-28T09:08:31-07:00",
"scrapedAt": "2026-10-28T16:08:32.273Z"
}

In that run, sizes 13.5, 14 and 15 of the Natural Grey Wool Cruiser showed variantAvailable: false. That is the size-level stock signal resellers and competitors watch, and it only shows up in variant mode.

What people use Shopify product data for

  • Competitor price monitoring. Schedule a daily run over your competitors' stores and compare price and compareAtPrice with yesterday's file. A new compare-at price means a markdown; available flipping to false means a sell-out.
  • Catalog and assortment research. Count products by productType and vendor, see which brands a retailer carries, and spot new launches by publishedAt.
  • Dropshipping and wholesale buying. Pull a supplier's catalog with SKUs, weights and images straight into a sheet instead of copying it by hand.
  • Brand protection (MAP checks). Brands check what price their products are listed at across many Shopify retailers.
  • Market and AI datasets. Clean, structured product data for analysis, product-matching models or a RAG index, without writing or maintaining a scraper.

Shopify scraper vs. doing it by hand

Opening products.json in a browser works for a quick look at a small store. It stops being practical when you need more than 250 products (manual paging), more than one store, a CSV, or anything on a schedule. You also get prices with no currency.

Writing your own Python script is a reasonable weekend project. The loop is simple; the edge cases are what take time:

  • stopping correctly (empty page, not short page) and handling the 25,000 cap
  • stores on custom domains, www redirects and stores that turned the feed off
  • adding currency from /meta.json
  • flattening variants into rows and handling compare_at_price that is null, "0.00" or lower than the price
  • polite rate limits so you are not blocked, retries on timeouts, robots.txt
  • somewhere to run it every day and store the results

Using the Actor costs $0.90 per 1,000 products, and those cases are already handled. It runs in the cloud on a schedule and connects to Sheets, Make, Zapier and n8n. For a store with 2,000 products checked daily, that is about $1.80 a day in product mode. If you only need one export, once, from one small store, the free browser method is fine and you do not need us.

Pricing

You pay per row saved: $0.90 per 1,000 products (Apify Silver plan $0.81, Gold $0.72), plus a $0.00005 start fee per run. In variant mode each variant row counts as one product. Stores that are not Shopify, or that have their feed turned off, cost nothing.

Worked examples: 3 stores × 2,000 products = 6,000 products = $5.40. 10,000 products = $9.00. The default example run above (100 products) costs $0.09.

FAQ

Is there an official Shopify API for scraping other stores? No. Shopify's Admin and Storefront APIs need the store owner's access token. The public products.json feed is the only open source of a store's catalog, and it is what this Actor reads.

Which stores work? Any Shopify storefront that serves its public product feed, which is most of them. If a store turned it off, the run says so for that store and carries on with the others.

Why is there no stock quantity? Shopify only publishes an in-stock yes/no to the public. Exact counts are private.

How do I get all products from a store with more than 25,000? Shopify blocks paging past 25,000 products in one feed. Run the Actor once per collection (set Collection to mens, womens, sale and so on). Each collection has its own 25,000 limit.

Are prices in USD? Prices are in the store's base currency, and the currency column (read from the store's /meta.json) tells you which one: USD, EUR, GBP and so on. Localised prices a store shows to visitors from other countries can differ from the base price in the feed.

How many products per store? All of them if you set Max products per store to 0. Pages of 250 are fetched politely, about one every 2 seconds per store.

Can I schedule it? Yes. Create a Task with your input and add a Schedule (daily, weekly, any cron). Each run gets a fresh dataset you can download or fetch via API.

Does it work with Make, Zapier, n8n or Google Sheets? Yes. Use the Apify app in Make, Zapier or n8n ("Run Actor", then "Get dataset items"), or the Google Sheets integration on the run's Integrations tab to append rows to a sheet automatically.

How do I keep costs predictable? Set Max results, or Maximum cost per run in the run options. The Actor stops cleanly at the cap and you are never billed past it.

Is scraping Shopify stores legal? The Actor only reads the feed the store itself publishes to every visitor without a login, follows robots.txt, keeps a polite request rate and collects no personal data. You are responsible for how you use the data: follow the site's terms, copyright and the privacy laws that apply to you.

This Actor only reads pages and feeds that the website itself publishes to every visitor without a login. It obeys each site's robots.txt, keeps a polite request rate, and never tries to get past logins, paywalls, captchas or bot checks. It does not collect personal data such as emails, phone numbers or names of private individuals. You are responsible for how you use the data: follow the source site's terms, copyright and the privacy laws that apply to you (GDPR, CCPA, etc.). This tool is independent and not affiliated with or endorsed by the platforms it reads.