# Shopify Products Scraper - Prices, Variants & Stock (`tenfoldfleet/shopify-products-scraper`) Actor

Scrape all products from a Shopify store or collection: title, prices, compare-at price, discount %, variants with SKU and stock, options, images, tags, vendor, description and currency. Works on headless stores too. No browser. $0.80 per 1,000 products; failed or non-Shopify stores are free.

- **URL**: https://apify.com/tenfoldfleet/shopify-products-scraper.md
- **Developed by:** [Tenfold Fleet](https://apify.com/tenfoldfleet) (community)
- **Categories:** E-commerce, Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 products

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does Shopify Products Scraper do?

**Shopify Products Scraper** extracts **every product from any [Shopify](https://www.shopify.com/) store** through the store's public product feed (`/products.json`) and returns clean, structured data: **title, prices, compare-at price, discount %, variants with SKU and stock, options, images, tags, vendor, product type, description, dates and store currency**.

Paste a **store URL** to get the whole catalogue, a **collection URL** to get one category, a **product URL** to get a single product, or a **store search URL** (`/search?q=runner`) to get the matching products. It also works on many **headless Shopify stores** (Hydrogen / Next.js frontends such as Gymshark or Fashion Nova): when the storefront hides the feed, the actor finds the store's `*.myshopify.com` address and reads the products from there.

It is a **Shopify product API** without an API key: plain HTTP requests, no browser, so it is fast (250 products per request) and cheap: **$0.80 per 1,000 products**.

### Why use a Shopify scraper?

- 💸 **Competitor price monitoring**: track prices, discounts and stock of competing Shopify stores every day.
- 🛍️ **Dropshipping and product research**: find what a store sells, its best price points, vendors and new launches (`createdAt`, `publishedAt`).
- 📦 **Catalogue migration and backup**: export a full product catalogue with variants, SKUs, options and image URLs to CSV or Excel.
- 🏷️ **Sale and discount tracking**: `compareAtPrice` and `discountPercent` show what is on sale and by how much.
- 📈 **Market and brand intelligence**: compare assortments, product types and tags across many brands at once.
- 🤖 **AI agents and data pipelines**: call it from the Apify API, MCP server, Make, Zapier or n8n and get clean JSON.

### What data can it extract?

| Field | Example |
|---|---|
| `store`, `storeName` | `allbirds.com`, `Allbirds` |
| `productId`, `handle`, `url` | `7340901859408`, `womens-tree-runner`, product page link |
| `title`, `vendor`, `productType` | `Women's Tree Runner`, `Allbirds`, `Shoes` |
| `tags` | `["womens", "sale"]` |
| `currency` | `USD` (store currency) |
| `priceMin`, `priceMax` | `25`, `120` |
| `compareAtPrice`, `discountPercent` | `50`, `50` |
| `available` | `true` if any variant is in stock |
| `variantCount`, `variants` | id, SKU, title, price, compare-at price, availability, option1-3 per variant |
| `options` | `[{ "name": "Size", "values": ["5", "6", "7"] }]` |
| `imageUrl`, `images` | image URLs on the Shopify CDN |
| `descriptionText` | description with HTML stripped |
| `createdAt`, `updatedAt`, `publishedAt` | ISO 8601 timestamps |

### How to scrape products from a Shopify store

1. Click **Try for free**.
2. Add one or more **store, collection or product URLs**, e.g. `allbirds.com` or `https://www.allbirds.com/collections/mens`.
3. Optionally set a **keyword filter**, a **max products per store**, or switch on **one row per variant**.
4. Click **Start** and download the products as **JSON, CSV, Excel or HTML**, or fetch them through the API.

### How much does it cost to scrape Shopify?

You pay **$0.0008 per product**, which is **$0.80 per 1,000 products**, plus a tiny **$0.00005 start fee per run**. With **One row per variant** on, each variant row counts as one result. Stores that fail (not Shopify, password-protected, blocked, empty collection, no keyword matches) and unsupported URLs (blog posts, about pages, filtered collections) are reported in the dataset with an `error` field and are **never charged**, so a typo never turns into a whole-store scrape. The same store pasted twice (`allbirds.com` and `www.allbirds.com`) is scraped and charged once. Set a maximum cost per run in the run options and the actor stops cleanly when it is reached. Apify's free monthly credit covers thousands of products.

### Input

```json
{
    "urls": [
        "https://www.allbirds.com/collections/mens",
        "kyliecosmetics.com",
        "gymshark.com",
        "https://www.allbirds.com/products/womens-tree-runners"
    ],
    "keyword": "runner, hoodie",
    "maxProductsPerStore": 0,
    "oneRowPerVariant": false,
    "includeDescription": true
}
```

### Output

```json
{
    "store": "allbirds.com",
    "storeName": "Allbirds",
    "productId": 7340901859408,
    "title": "Women's Allbirds Flip Flop - Dusty Pink",
    "handle": "womens-allbirds-flip-flop-dusty-pink",
    "url": "https://www.allbirds.com/products/womens-allbirds-flip-flop-dusty-pink",
    "vendor": "Allbirds",
    "productType": "Shoes",
    "tags": ["allbirds::gender => womens", "shoprunner"],
    "currency": "USD",
    "priceMin": 25,
    "priceMax": 25,
    "compareAtPrice": 50,
    "discountPercent": 50,
    "available": true,
    "variantCount": 7,
    "variants": [
        { "id": 42146889039952, "sku": "A12513W050", "title": "5", "price": 25, "compareAtPrice": 50, "available": false, "option1": "5", "option2": null, "option3": null }
    ],
    "options": [{ "name": "Size", "values": ["5", "6", "7", "8", "9", "10", "11"] }],
    "imageUrl": "https://cdn.shopify.com/s/files/1/1104/4168/files/A12513_PDP_LEFT.png",
    "images": ["https://cdn.shopify.com/s/files/1/1104/4168/files/A12513_PDP_LEFT.png"],
    "descriptionText": "Sun on your feet. Comfort underneath...",
    "createdAt": "2026-03-27T21:03:50.000Z",
    "updatedAt": "2026-10-01T02:35:59.000Z",
    "publishedAt": "2026-09-25T23:58:13.000Z",
    "collection": null,
    "input": "allbirds.com",
    "scrapedAt": "2026-10-01T09:00:00.000Z"
}
```

With **One row per variant**, each row also has `variantId`, `variantTitle`, `sku`, `price`, `option1`-`option3`, and `compareAtPrice`, `discountPercent` and `available` refer to that variant. The full `images` list and `descriptionText` are on the first variant row of each product (every row keeps `imageUrl`); the **Variants** view in the Output tab shows SKU, variant and price columns. You can download the dataset in various formats such as JSON, HTML, CSV, or Excel. Failed inputs appear as `{ "input": "...", "error": "..." }` rows.

### Tips

- **Collection URLs are cheaper than whole stores** when you only need one category.
- Product-level `compareAtPrice` and `discountPercent` come from the **cheapest in-stock variant**; switch on one row per variant to see every variant's discount.
- Shopify serves at most **25,000 products per listing**. When a listing hits that limit you get a notice row; add collection URLs to get the rest.
- **Max products per store** counts products. With one row per variant on, 100 products can mean thousands of rows, so set a **maximum cost per run** as well.
- Schedule the actor daily on the same stores to build a **price history** or catch new products.
- Prices are in the store's base currency (`currency`), as published in its product feed.

### FAQ

#### Does it work on any Shopify store?

On any store that has a public storefront. Password-protected stores and stores that block automated traffic return a free error row. Headless stores work when their `*.myshopify.com` domain is discoverable; you can also paste that domain directly.

#### How do I know if a website is a Shopify store?

Just add it. Non-Shopify sites return a free `Not a Shopify store` error row, so testing a list of domains costs only the $0.00005 run start fee.

#### Do I need a Shopify API key or login?

No. The actor only reads public product data that the store publishes to every visitor.

#### Is inventory quantity included?

Shopify's public feed shows whether each variant is **available** (in stock), not exact stock counts. If a store hides stock entirely, `available` is `null` (unknown) rather than a wrong `false`.

#### Which URLs can I paste?

The store home page, `/collections/<handle>`, `/products/<handle>` and `/search?q=<term>` URLs, with or without a language prefix like `/en-gb/`. Anything else returns a free error row that tells you which URL to use instead.

#### What happens if the run stops or restarts?

The actor saves its progress, so if Apify restarts the run on another server it continues where it left off instead of charging again. If your maximum cost per run is reached, inputs that were not started get a free `Not processed` row.

#### Can I use it from code or AI agents?

Yes, through the Apify API, the JavaScript or Python client, or the Apify MCP server.

#### Support

Found a Shopify store that does not parse? Open an issue in the **Issues** tab.

This actor only reads publicly available product information from Shopify storefronts. It does not log in, bypass password pages or access controls, or collect personal data.

### More tools from Tenfold Fleet

| Actor | Price |
|---|---|
| [ATS Jobs Scraper - Greenhouse, Lever, Ashby & 5 More](https://apify.com/tenfoldfleet/ats-jobs-scraper) | $2 per 1,000 (job posting) |
| [Website Contact Scraper - Emails, Phones & Socials](https://apify.com/tenfoldfleet/company-contact-finder) | $8 per 1,000 (website with contacts) |
| [Google Ads Transparency Center Scraper - Competitor Ads by Site](https://apify.com/tenfoldfleet/google-ads-transparency-scraper) | $1 per 1,000 (ad scraped) |
| [Google News Scraper - Articles, Real URLs & Full Text](https://apify.com/tenfoldfleet/google-news-scraper) | $2 per 1,000 (article) |
| [Keyword Search Volume, CPC & Difficulty Checker (Bulk)](https://apify.com/tenfoldfleet/keyword-search-volume) | $5 per 1,000 (keyword with data) |
| [Remote Jobs Aggregator - RemoteOK, WWR, Himalayas & 4 more](https://apify.com/tenfoldfleet/remote-jobs-aggregator) | $1.2 per 1,000 (unique remote job) |
| [SEO Audit Tool - Technical On-Page SEO Checker & Score](https://apify.com/tenfoldfleet/seo-audit-tool) | $20 per 1,000 (page audited) |
| [Shopify App & Theme Detector - Store Analyzer & Contacts](https://apify.com/tenfoldfleet/shopify-store-analyzer) | $8 per 1,000 (shopify store analyzed) |
| [Sitemap URL Extractor - All URLs from sitemap.xml & robots.txt](https://apify.com/tenfoldfleet/sitemap-url-extractor) | $0.4 per 1,000 (url extracted) |
| [Technology Detector - Wappalyzer & BuiltWith Alternative](https://apify.com/tenfoldfleet/tech-stack-detector) | $10 per 1,000 (website analyzed) |
| [URL to Markdown - Web Page to LLM-Ready Text for AI Agents](https://apify.com/tenfoldfleet/url-to-markdown) | $1 per 1,000 (page converted) |
| [Workday Jobs Scraper - myworkdayjobs.com API with Salary](https://apify.com/tenfoldfleet/workday-jobs-scraper) | $1.5 per 1,000 (job posting) |
| [YouTube Comments Scraper - Replies, Likes & Sort by Newest](https://apify.com/tenfoldfleet/youtube-comments-scraper) | $0.6 per 1,000 (comment scraped) |
| [YouTube Transcript Scraper - Captions & Subtitles API](https://apify.com/tenfoldfleet/youtube-transcript-scraper) | $3 per 1,000 (transcript extracted) |

# Actor input Schema

## `urls` (type: `array`):

One per line. A store (allbirds.com or https://shop.example.com) scrapes the whole catalogue; a collection URL (https://www.allbirds.com/collections/mens) scrapes only that collection; a product URL scrapes one product; a store search URL (https://www.allbirds.com/search?q=runner) keeps products matching the search term. \*.myshopify.com addresses work too. Other pages (blogs, about, filtered collections) are rejected with a free error row instead of scraping the whole store.

## `keyword` (type: `string`):

Only keep products whose title, vendor, product type, tags or handle contain this text (case-insensitive). Separate several keywords with commas to match any of them, e.g. hoodie, t-shirt. You are only charged for products that match. A /search?q= URL uses its own search term instead.

## `maxProductsPerStore` (type: `integer`):

Stop after this many products per store or collection (after the keyword filter). 0 = all products. With 'One row per variant' on, each product can produce many rows (one per size/colour), and each row is one result. Shopify serves at most 25,000 products per listing; add collection URLs to go beyond that.

## `oneRowPerVariant` (type: `boolean`):

Output one row per variant (size/colour) with its own SKU, price, compare-at price and stock instead of one row per product with a nested variants list. Better for spreadsheets and price tracking. Each variant row is one result. The full image list and description are on the first variant row of each product.

## `includeDescription` (type: `boolean`):

Add the product description as plain text (HTML stripped). Turn off for smaller results.

## Actor input object example

```json
{
  "urls": [
    "https://www.allbirds.com/collections/mens",
    "kyliecosmetics.com"
  ],
  "maxProductsPerStore": 100,
  "oneRowPerVariant": false,
  "includeDescription": true
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `variants` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        "https://www.allbirds.com/collections/mens",
        "kyliecosmetics.com"
    ],
    "maxProductsPerStore": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("tenfoldfleet/shopify-products-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "urls": [
        "https://www.allbirds.com/collections/mens",
        "kyliecosmetics.com",
    ],
    "maxProductsPerStore": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("tenfoldfleet/shopify-products-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "urls": [
    "https://www.allbirds.com/collections/mens",
    "kyliecosmetics.com"
  ],
  "maxProductsPerStore": 100
}' |
apify call tenfoldfleet/shopify-products-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tenfoldfleet/shopify-products-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/0RNntXezqE0n7K9Kf/builds/11GwvM9bsNaGHAc8b/openapi.json
