---
title: "How to Scrape Any Shopify Store (2026) | Scrape.ly"
description: "A Shopify scraper that turns any public store into rows: products, variants, prices, sale prices and stock per size, with a real run, its cost and code."
url: https://scrape.ly/blog/scrape-shopify-stores
markdown: https://scrape.ly/blog/scrape-shopify-stores.md
---

[Tutorials](https://scrape.ly/blog/category/tutorials.md)

# 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.

[Shelfbright Actor publisher on the Scrape.ly Store](https://scrape.ly/blog/author/shelfbright.md)

- Published

  Oct 23, 2026

- 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](https://scrape.ly/media/scrape-shopify-stores.png?w=1080)

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](https://scrape.ly/store/shelfbright/shopify-scraper.md) 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](https://scrape.ly/store/shelfbright/shopify-scraper/presets/other-store-price-filter.md). "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
}
```

4. Click **Start**. Our run took 6 seconds.
5. 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](https://scrape.ly/store/shelfbright/shopify-scraper/presets/real-inventory-addon.md) turns on real inventory; [Kith tops with recommendations](https://scrape.ly/store/shelfbright/shopify-scraper/presets/storefront-recommendations.md) 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/`.

Scrape.ly Store Shopify Scraper Any public Shopify store, collection or product: variants, prices, sale prices, stock status, SKUs, weights and images, one row per product. $0.50 per 1,000 products.

[Try it free](https://scrape.ly/store/shelfbright/shopify-scraper.md) [Browse the Store](https://scrape.ly/store.md)

## 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](https://scrape.ly/docs/api-actors.md) 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](https://scrape.ly/api/shopify-api.md) 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:

```plaintext
20261023T03:02:29.106Z [Scrapely] Container started (setup 2.0 s)
20261023T03:02:30.418Z [scrapely.proxy_configuration] INFO  Platform proxy access check succeeded.
20261023T03:02:32.596Z [scrapely.actor] INFO  Saved 10 products and 0 collections. datacenter_bytes=76252 residential_bytes=0
20261023T03: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.

## Is it legal to scrape a Shopify store?

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](https://shopify.dev/docs/api/storefront)), 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](https://scrape.ly/store/shelfbright/google-shopping-scraper.md), Amazon and eBay, as in our [price scraping](https://scrape.ly/blog/price-scraping.md) guide. For marketplace sellers, the [eBay guide](https://scrape.ly/blog/how-to-scrape-ebay.md) 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.

Scrape.ly Store Scrape any Shopify store Run the Allbirds preset as-is, or paste the store or collection you want to track. Variants, prices, sale prices and stock per size. $0.50 per 1,000 products.

[Try it free](https://scrape.ly/store/shelfbright/shopify-scraper.md) [Browse the Store](https://scrape.ly/store.md)

About the author

[Shelfbright](https://scrape.ly/blog/author/shelfbright.md) 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.

- [Website](https://scrape.ly/users/shelfbright.md)

Keep reading

## More in Tutorials

- [![Pixel-art robot with an orange >\_ on its terminal head lifts a search result off a results page headed by the blue Bing logo and a search box, and drops it into a crate](https://scrape.ly/media/scrape-bing-search-results.png?w=750)](https://scrape.ly/blog/scrape-bing-search-results.md)
  ### [How to Scrape Bing Search Results: Rankings, Related Searches and News](https://scrape.ly/blog/scrape-bing-search-results.md)
  [Scrape Bing search results in any of 38 markets and get every results page as JSON: organic rankings with titles, URLs and dates, related searches, People Also Ask and the top news story. A real run, the cost per page, and code for curl, Python, Node.js and AI agents.](https://scrape.ly/blog/scrape-bing-search-results.md)
- [![Pixel-art robot with an orange >\_ on its terminal head pulls a product card with a photo and an orange price off a market stall with a striped awning, handmade goods on its counter and the orange Etsy logo on its sign, and drops it into a crate](https://scrape.ly/media/scrape-etsy.png?w=750)](https://scrape.ly/blog/scrape-etsy.md)
  ### [How to Scrape Etsy Data: Products, Prices and Shops](https://scrape.ly/blog/scrape-etsy.md)
  [Scrape Etsy by keyword or paste shop, category and listing URLs, and get each product as a row: price, sale price, shop name and rating, favorites, variations, photos and related searches. A real run, its cost, and code for curl, Python, Node.js and AI agents.](https://scrape.ly/blog/scrape-etsy.md)
- [![Pixel-art robot with an orange >\_ on its terminal head pulls a review card with five green rating bubbles out of a hotel tower whose sign shows the green Tripadvisor owl logo, and drops it into a crate](https://scrape.ly/media/scrape-tripadvisor.png?w=750)](https://scrape.ly/blog/scrape-tripadvisor.md)
  ### [How to Scrape Tripadvisor: Hotels, Restaurants, Attractions and Reviews](https://scrape.ly/blog/scrape-tripadvisor.md)
  [Scrape Tripadvisor hotels, restaurants and attractions by city or URL, then pull the reviews: ratings, rankings, prices, contacts, trip types and owner replies. Two real runs, their exact cost, and code for curl, Python, Node.js and AI agents.](https://scrape.ly/blog/scrape-tripadvisor.md)

## 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.

[Get Started Free](https://my.scrape.ly/register) [Chat with Support](mailto:support@scrape.ly?subject=Question%20about%20Scrape.ly\&body=Hi%2C%20I%20have%20a%20question%20about%20Scrape.ly.)

No credit card. No setup calls.
