Skip to content

How to Scrape Any Shopify Store: Products, Prices and Variants

Scrape any public Shopify store from a store, collection or product URL and get one row per product with every variant, price, sale price, stock status, SKU, weight and image. A real run on Allbirds, its cost, and code for curl, Python, Node.js and AI agents.

Published
Reading time
8 min read
Pixel-art robot with an orange >_ on its terminal head pulls a product card with a photo and a green price out of a shop front with a green-striped awning and the green Shopify bag logo on its sign, and drops it into a crate
In this article
  1. What data you can get from a Shopify store
  2. How to run the Shopify scraper without code
  3. How to scrape Shopify products with the API
  4. A real run: Allbirds men's shoes from $50 to $150
  5. What it costs
  6. What to watch out for when scraping Shopify stores
  7. Is it legal to scrape a Shopify store?
  8. Why Scrape.ly for Shopify data
  9. FAQ
  10. Can you scrape any Shopify store?
  11. How do I scrape Shopify products with Python?
  12. Can I scrape Shopify stock levels?
  13. Does a Shopify store's products.json still work?
  14. How much does it cost to scrape a Shopify store?

To scrape a Shopify store, point a Shopify scraper at the store's home page, a collection or a product URL, and it reads the store's public product data and saves one row per product: title, brand, every variant with its price and stock status, the sale price, SKUs, weights, images and tags. On Scrape.ly that's the Shopify Scraper. It works on any public Shopify storefront without a login or API key, and it costs $0.50 per 1,000 products.

This guide covers the fields, the no-code steps, the API (curl, Python, Node.js and MCP), the cost and the pitfalls. Everything comes from a real run on 23 October 2026: men's shoes between $50 and $150 from Allbirds, 10 products and 130 variants in 6 seconds.

What data you can get from a Shopify store

The Shopify Scraper writes one row per product. A /collections URL returns one row per collection instead.

Field What it holds
source Store product ID, canonical URL, retailer name, language, currency, and created, updated and published timestamps
title, brand, categories, tags Product identity, including the store's own tags
description The product description as HTML
price.current, price.previous Current price and compare-at (pre-sale) price, in minor units
price.stockStatus InStock, OutOfStock or LowInStock
priceRange Lowest and highest variant price, and whether they differ
options Option names and values, such as every size
variants[] Per variant: ID, title, SKU, options, price, stock status, weight in grams, taxable and requires-shipping flags
medias[] Product images with URL and alt text
fullyOutOfStock true when every variant is sold out

Prices are integers in minor units: 14000 means 140.00 in source.currency. Product pages add barcodes, tax codes and per-size availability. Opt-in extras add real stock counts (grabRealInventory), related products (maxRecommendationsPerProduct), selling plans and videos (grabStorefrontDetail) and information panels such as materials or care (grabContentSections).

How to run the Shopify scraper without code

  1. Open the Actor's page in the Scrape.ly Store and sign in.
  2. Pick a ready-made input. We ran the preset Allbirds men's shoes, 50 to 150 USD, 10 products. "Try this input" opens it in the console.
  3. Swap in the store or collection you want to track. This is the exact input of our run:
json
{
  "startUrls": [{ "url": "https://www.allbirds.com/collections/mens" }],
  "minPrice": 50,
  "maxPrice": 150,
  "maxResults": 10
}
  1. Click Start. Our run took 6 seconds.
  2. Export the products as JSON, CSV or Excel.

The fields that matter most:

  • startUrls (required): a store home page crawls the whole catalog, a collection URL crawls that collection, a product URL saves that product, and a URL ending in /collections lists the store's collections. Several stores can go in one run.
  • maxResults: records to save for the whole run (default 10). 0 means no limit, so set a maximum charge first.
  • minPrice, maxPrice: a price window in the store's currency (140 means 140.00), applied to the lowest variant.
  • query: search each store for a keyword instead of crawling the URL path. It uses the store's public suggestions and returns at most 10 products per store.
  • Extras: the preset Palettes with stock counts turns on real inventory; Kith tops with recommendations adds related products and storefront details.

To read prices in another currency, add ?currency=EUR to the start URL or use a locale path such as /en-gb/.

How to scrape Shopify products with the API

Create an API token under Settings → API & Integrations and export it as SCRAPELY_TOKEN. The Actors API docs list every endpoint.

curl. A 10-product run takes seconds, well inside the 45-second limit of the synchronous endpoint, which returns the products as a JSON array (add ?format=csv for CSV):

shell
curl -X POST "https://api.scrape.ly/v2/actors/shelfbright~shopify-scraper/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"startUrls": [{"url": "https://www.allbirds.com/collections/mens"}], "minPrice": 50, "maxPrice": 150, "maxResults": 10}'

For a full catalog, use the asynchronous flow (/runs, then /v2/actor-runs/RUN_ID?waitForFinish=60) or one of the clients: a 10,000-product store took about 22 minutes in the publisher's test.

Python (pip install scrapely-client-python). call() waits however long the run takes. This example prints price, sale price and how many sizes are in stock, the three numbers a competitor tracker needs:

python
import os
from scrapely_client import ScrapelyClient

client = ScrapelyClient(os.environ["SCRAPELY_TOKEN"], api_url="https://api.scrape.ly")

run = client.actor("shelfbright/shopify-scraper").call(
    run_input={"startUrls": [{"url": "https://www.allbirds.com/collections/mens"}],
               "minPrice": 50, "maxPrice": 150, "maxResults": 10}
)
print(run.status)  # SUCCEEDED, FAILED, ABORTED or TIMED-OUT
for p in client.dataset(run.default_dataset_id).iterate_items():
    price = p["price"]["current"] / 100
    was = p["price"]["previous"] / 100 or None
    in_stock = sum(v["price"]["stockStatus"] != "OutOfStock" for v in p["variants"])
    print(f'{price:7.2f}  was {was or "-":>6}  {in_stock:2}/{len(p["variants"])} sizes  {p["title"]}')

Node.js (npm install scrapely-client):

javascript
import { ScrapelyClient } from 'scrapely-client';

const client = new ScrapelyClient({ token: process.env.SCRAPELY_TOKEN, baseUrl: 'https://api.scrape.ly' });

const run = await client.actor('shelfbright/shopify-scraper').call({
  startUrls: [{ url: 'https://www.allbirds.com/collections/mens' }],
  minPrice: 50,
  maxPrice: 150,
  maxResults: 10,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map((p) => [p.title, p.price.current / 100, p.price.stockStatus, p.source.canonicalUrl]));

AI agents (MCP). Add the hosted Scrape.ly MCP server. In Cursor, put this in ~/.cursor/mcp.json:

json
{
  "mcpServers": {
    "scrapely": {
      "url": "https://api.scrape.ly/mcp",
      "headers": { "Authorization": "Bearer YOUR_TOKEN" }
    }
  }
}

In Claude Code, run claude mcp add --transport http scrapely https://api.scrape.ly/mcp and sign in with /mcp. Then ask: "Use scrapely to run shelfbright/shopify-scraper on https://www.allbirds.com/collections/mens, 20 products, and give me a table of product, price, sale price and sizes in stock." The agent reads the input with fetch-actor-details, runs it with call-actor and reads the rows with get-actor-output. The Shopify API page shows the same Actor as an API product.

A real run: Allbirds men's shoes from $50 to $150

We ran the preset on 23 October 2026. It saved 10 products in 6 seconds of run time and was charged $0.0059. The first five:

Product Price Was Sizes in stock Status
Men's Dasher NZ - Anthracite (Dark Anthracite Sole) $140.00 – 6 of 13 InStock
Men's Dasher NZ - Light Burnt Olive (Natural White Sole) $140.00 – 4 of 13 InStock
Men's Dasher NZ - Blizzard (Blizzard Sole) $140.00 – 13 of 13 InStock
Men's Dasher NZ - Blizzard/Deep Navy (Blizzard Sole) $140.00 – 0 of 13 OutOfStock
Men's Dasher NZ - Dark Eucalyptus (Dark Eucalyptus Sole) $99.00 $140.00 9 of 13 InStock

What the full run shows:

  • One product line, many rows. Eight of the ten products were colorways of the Dasher NZ at $140; the other two were Cruiser canvas shoes at $75. Allbirds lists each colorway as its own Shopify product, so a "product" in Shopify terms is often a single color.
  • Stock is the real signal. The ten products had 130 size variants (sizes 8 to 15), and 73 of them, 56%, were in stock. One colorway was sold out in every size, two were in stock in all 13.
  • Sales show up as fields. One colorway was marked down to $99 from $140, which you see in price.previous without parsing a strikethrough price.
  • Variants carry SKUs and weights. Every size has its own SKU and shipping weight (914 g for a US 8 of the first shoe), which is what you need to match products across retailers.
  • Tags reveal the store's taxonomy. Allbirds' tags include its internal material, silhouette and price-tier labels, useful for grouping a competitor's catalog the way they do.

The log, without the platform's start-up lines:

Text
2026-10-23T03:02:29.106Z [Scrapely] Container started (setup 2.0 s)
2026-10-23T03:02:30.418Z [scrapely.proxy_configuration] INFO  Platform proxy access check succeeded.
2026-10-23T03:02:32.596Z [scrapely.actor] INFO  Saved 10 products and 0 collections. datacenter_bytes=76252 residential_bytes=0
2026-10-23T03:02:33.362Z [Scrapely] Container state: status=exited exitCode=0 oomKilled=false

Reading the collection and saving ten products took about 2 seconds over the default datacenter proxy, using 76 KB of traffic and no residential bandwidth.

What it costs

The Actor charges $0.0005 per product saved ($0.50 per 1,000). Extras are separate opt-in events: $0.0003 per product with a real stock count, $0.0003 per nested related product, $0.0003 per collection row and $0.0001 per product with information panels. Platform usage (compute and storage) is billed on top.

For our run: 10 products × $0.0005 = $0.005 in product fees. The run was charged $0.0059 in total: $0.0008 of compute, $0.00005 of dataset writes and $0.00001 of proxy traffic. A 1,000-product catalog costs $0.50 in product fees; a product reached twice in the same run is saved and charged once. A store that doesn't publish stock counts isn't charged for inventory.

What to watch out for when scraping Shopify stores

  • Not every store is Shopify. On a site that isn't, the run succeeds, saves nothing and says so in the status line, so a wrong URL costs you nothing in product fees.
  • Password-protected storefronts are skipped. Only public stores can be read.
  • Prices are in minor units. Divide by 100 for dollars and euros, and check source.currency before you compare stores.
  • Stock counts are not stock status. Every variant comes with in stock or out of stock. A number of units only appears with real inventory on and when the store publishes one; LowInStock means a real count of 1 to 5.
  • maxResults is per run. It counts across all stores in the input, not per store.
  • Keyword search is for spot checks. query uses the store's own search suggestions, which return up to 10 products per store. Crawl a collection or the home page when you need everything.
  • Datacenter first. Datacenter proxies are the default and were enough here. Switch to residential only if a store refuses datacenter addresses.

The Actor reads only public product data, the same catalog any shopper sees, and it skips password-protected stores. Product titles, prices, variants and stock status are commercial facts about products, not personal data, which makes catalog scraping one of the lower-risk kinds of scraping.

Each store has its own terms of service, and they may set rules for automated access or reuse of descriptions and images. Read the terms of the stores you track before you build a product on their data. Product photos and descriptions are usually copyrighted, so use them for analysis rather than republishing them. Keep your request volume modest; the Actor's defaults are light, as the 76 KB in our log shows. This is general information, not legal advice: for commercial use, ask a lawyer about your case.

Why Scrape.ly for Shopify data

  • One input for every store. Bright Data's Python tutorial appends /products.json to a store URL and pages through it by hand. That works store by store, but you write the pagination, price conversion, stock logic and retries yourself. The Actor takes any store, collection or product URL and returns the same fields every time.
  • The official API isn't built for this. Shopify's Storefront API answers product queries without a token, but product tags and metafields need an access token (shopify.dev), and you write GraphQL queries per store. The Actor returns tags, variants and stock with no token and no queries.
  • Cheap enough to run daily. $0.50 per 1,000 products, and our run cost $0.0059. Schedule a competitor's collection every morning and send the rows to Google Sheets or a webhook.
  • Part of a full pricing stack. Combine Shopify stores with the Google Shopping Scraper, Amazon and eBay, as in our price scraping guide. For marketplace sellers, the eBay guide adds condition and sold counts.

FAQ

Can you scrape any Shopify store?

Any public Shopify storefront, yes. Password-protected stores are skipped, and sites that aren't Shopify return nothing (and cost nothing in product fees). Paste a home page for the full catalog, a collection or a single product.

How do I scrape Shopify products with Python?

Install scrapely-client-python, call shelfbright/shopify-scraper with startUrls and maxResults, and iterate over the dataset, as in the example above. Divide prices by 100 to get dollars.

Can I scrape Shopify stock levels?

Every variant comes with a stock status. Turn on Real inventory counts (grabRealInventory) to add the number of units per variant when the store publishes it, at $0.0003 per product that has one.

Does a Shopify store's products.json still work?

On many stores, yes: Allbirds' /products.json returned products when we checked on 23 October 2026. It gives you raw JSON one page at a time. The Shopify Scraper reads the store's public product data for you and returns clean, filtered rows with stock status per variant.

How much does it cost to scrape a Shopify store?

$0.50 per 1,000 products, plus small usage and any extras you turn on. Our 10-product run was charged $0.0059. The Free plan's $5 of monthly credit covers about 10,000 products in product fees.

  • shopify
  • ecommerce
  • price monitoring
  • competitor analysis
  • python
  • api

About the author

Actor publisher on the Scrape.ly Store

Prices, stock and seller data from shops and marketplaces, from Amazon and AliExpress to Vinted and Leboncoin. For price trackers, catalogue teams and resellers. A Scrapely studio.

//Keep reading\\

The internet is full of data.
Start owning yours.

Scrape.ly gives you the infrastructure, the tooling, and the team to extract, process, and operationalize web data at any scale. Setup takes minutes. The advantage lasts forever.

No credit card. No setup calls.