# Shopify Store Scraper — Products, Prices, Store Info (`actor-forge/shopify-store-scraper`) Actor

Scrape any Shopify store's products from its public products.json: title, vendor, type, tags, price range, compare-at price, stock, variants and images. Or get one store row: shop info, product count, price stats, top vendors, theme and apps. $0.30 per 1,000 products.

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

## Pricing

from $0.30 / 1,000 product results

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

## Shopify Store Scraper — Products, Prices, Store Info

Scrape any Shopify store's products from its public products.json: title, vendor, type, tags, price range, compare-at price, stock, variants and images. Or get one store row: shop info, product count, price stats, top vendors, theme and apps. $0.30 per 1,000 products.

**A Shopify scraper for products, prices and store data.** Give it one or more Shopify store URLs and it reads each store's public **products.json** feed, the same JSON catalogue Shopify serves to every visitor. You get one clean row per product: title, handle, vendor, product type, tags, created/published/updated dates, **price range**, **compare-at price** and discount %, stock availability, every **variant** (SKU, price, compare-at, options, weight) and every image URL. It works as a **Shopify products scraper** for catalogue exports, product research and dropshipping, and for **competitor price monitoring**: schedule a daily run with `updatedSince` and you only get (and pay for) the products that changed. Use `collections` to scrape just one collection. Switch `mode` to **store** for one **Shopify store data** row per shop: name, country, currency, ships-to countries, published product and collection counts (from meta.json), price stats (min/median/average/max, % on sale), top vendors, product types and tags, the biggest collections, the **theme** (name, base theme, version) and the **apps** detected on the homepage (Klaviyo, Rebuy, Yotpo, Afterpay and 7,600+ other fingerprints). It uses plain HTTP at 256 MB, an honest user agent, the store's own robots.txt and a polite 1.3 requests/second per store. **$0.30 per 1,000 products, $0.005 per analysed store.** Blocked, headless and non-Shopify sites are free.

📘 **Step-by-step guide:** [How to Export Shopify Store Product Data to CSV or JSON](https://devtaonas.github.io/actorforge-site/guides/export-shopify-store-product-data/)

### What data does it return?

Every run outputs clean, schema-validated rows like these:

| store | title | vendor | productType | price | compareAtPriceMin | discountPct | available | variantCount |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| www.allbirds.com | Women's Allbirds Flip Flop - Dusty Pink | Allbirds | Shoes | 25 | 50 | 50 | true | 7 |
| www.allbirds.com | Men's Canvas Runner NZ - Deep Navy Stripes (Blizzard Sole) | Allbirds | Shoes | 100 |  |  | true | 13 |
| www.tentree.com | Sasquatch Peak Hat | tentree | Accessories | 31.5 | 45 | 30 | true | 1 |
| www.deathwishcoffee.com | White Chocolate Pistachio Ground Bundle | Death Wish Coffee | Bundle | 48.99 | 53.99 | 9.3 | true | 1 |

### How much does it cost?

Transparent pay-per-event pricing — you only pay for what you get, and the
actor **always respects your run budget**: set a maximum total charge and it
stops cleanly at the cap instead of overrunning.

| Event | Price | Charged | Worked example |
| --- | --- | --- | --- |
| `product-result` | $0.0003 | per product row delivered (with variants and images) | A 1,000-product store = $0.30; with updatedSince, unchanged products are skipped and cost nothing |
| `store-analyzed` | $0.005 | per store row in store/both mode (meta, price stats, top vendors/types, collections, theme, apps) | 100 competitor stores = $0.50; blocked, headless, robots-disallowed and non-Shopify sites are free rows |
| `apify-actor-start` | $0.00005 | per run per GB of memory (platform start fee) | One run at 256 MB = $0.0000125 |

### Input options

| Field | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `storeUrls` | array | no | — | Store domains or URLs, e.g. allbirds.com or https://www.allbirds.com/collections/mens. Any page of the store works because the store is taken from the host. myshopify.com domains work too. Duplicates are removed. |
| `storeUrl` | string | no | — | One store domain or URL. Handy for Clay, Make/Zapier and AI agents. Scraped together with storeUrls. |
| `mode` | string | no | `"products"` | products: one row per product ($0.30 per 1,000). store: one row per shop with meta.json details, product count, price stats, top vendors/types/tags, top collections, theme and detected apps ($0.005 per store). both: product rows plus the store row. |
| `collections` | array | no | `[]` | Optional collection handles (the part after /collections/ in the URL, e.g. mens-shoes). When set, products come from each collection instead of the whole catalogue, and each row says which collection it came from. Applied to every store in the run. |
| `maxProductsPerStore` | integer | no | `1000` | Stop each store after this many product rows (products/both mode), or after scanning this many products for the stats (store mode). products.json returns 250 products per page. |
| `updatedSince` | string | no | `""` | Optional date (YYYY-MM-DD) or ISO timestamp. Only products whose updated_at is on or after it become rows. Products skipped by this filter are never charged. Use it for daily price and stock monitoring. |
| `includeVariants` | boolean | no | `true` | Add every variant (SKU, price, compare-at price, availability, options, weight) to each product row. Same price. |
| `includeBodyHtml` | boolean | no | `false` | Add the product description (body_html) to each row. Off by default because it makes rows much bigger. Same price. |

### Limits & honest notes

- Only stores that serve Shopify's public /products.json work. Headless storefronts (Hydrogen/Oxygen or a custom frontend, e.g. fashionnova.com, hydrogen.shop) do not serve it and come back as free not-reachable rows.
- Each store's own robots.txt is read first and obeyed, including any Crawl-delay. The actor never requests /search, /cart, /checkout, /policies/, /recommendations/products or sort_by collection URLs. A store that disallows products.json gives a free robots-disallowed row.
- Polite by design: one request at a time per store at about 1.3 requests/second, at most 3 stores in parallel, honest user agent (ActorForge-ShopifyScraper/1.0). A 401/403/429 or bot challenge stops that store at once: no retries, proxies or bypass. Some big brands (e.g. gymshark.com with a 403, bombas.com with a Vercel challenge) block this, so their rows are free.
- products.json returns 250 products per page and lists published products only. maxProductsPerStore caps each store (default 1,000, up to 100,000). In both mode the store stats cover the products scanned, and catalogComplete says whether that was the whole catalogue.
- Prices are the store's base-currency prices from products.json (meta.json gives the currency). Market-specific or B2B prices, inventory quantities and sales figures are not public there.
- Apps and theme come from the homepage HTML (Shopify.theme and the open webappanalyzer fingerprints). Apps that load only after JavaScript runs or only on product pages may be missed.
- Catalogue data only: no customer, reviewer or contact-person data is read or returned.
- The run's spend limit is respected: products are charged one page at a time before delivery, and the run stops cleanly when the limit is reached.

### Related ActorForge actors

- [Tech Stack Detector — Wappalyzer Alternative, Bulk Lookup](https://apify.com/actor-forge/tech-stack-detector) — find which sites run Shopify (and which apps) across a big domain list first; $1.50 per 1,000 sites
- [Domain Enrichment for Clay — Tech, DNS, WHOIS, Logo & Socials](https://apify.com/actor-forge/domain-enrichment) — turn the stores into company rows: logo, socials, contact page, email provider, domain age
- [Website Change Monitor — Page Diff, CSS Selector & Webhook](https://apify.com/actor-forge/website-change-monitor) — watch one competitor page (a price, a banner, a policy) and get a webhook when it changes
- **Learn more:** [How to Export Shopify Store Product Data to CSV or JSON](https://devtaonas.github.io/actorforge-site/guides/export-shopify-store-product-data/)

### Changelog

- **2026-10-20** — Initial release: products.json pagination (250/page), collection filter, updatedSince, variants and images, optional body_html; store mode with meta.json, price stats, top vendors/types/tags, top collections, theme and app detection; robots.txt, Crawl-delay and stop-on-block compliance.

***

*Built and maintained by **ActorForge**. Reliability first: every actor in the
portfolio is monitored by an automated nightly self-test, and breakages are
typically fixed the same day.*

# Actor input Schema

## `storeUrls` (type: `array`):

Store domains or URLs, e.g. allbirds.com or https://www.allbirds.com/collections/mens. Any page of the store works because the store is taken from the host. myshopify.com domains work too. Duplicates are removed.

## `storeUrl` (type: `string`):

One store domain or URL. Handy for Clay, Make/Zapier and AI agents. Scraped together with storeUrls.

## `mode` (type: `string`):

products: one row per product ($0.30 per 1,000). store: one row per shop with meta.json details, product count, price stats, top vendors/types/tags, top collections, theme and detected apps ($0.005 per store). both: product rows plus the store row.

## `collections` (type: `array`):

Optional collection handles (the part after /collections/ in the URL, e.g. mens-shoes). When set, products come from each collection instead of the whole catalogue, and each row says which collection it came from. Applied to every store in the run.

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

Stop each store after this many product rows (products/both mode), or after scanning this many products for the stats (store mode). products.json returns 250 products per page.

## `updatedSince` (type: `string`):

Optional date (YYYY-MM-DD) or ISO timestamp. Only products whose updated_at is on or after it become rows. Products skipped by this filter are never charged. Use it for daily price and stock monitoring.

## `includeVariants` (type: `boolean`):

Add every variant (SKU, price, compare-at price, availability, options, weight) to each product row. Same price.

## `includeBodyHtml` (type: `boolean`):

Add the product description (body_html) to each row. Off by default because it makes rows much bigger. Same price.

## Actor input object example

```json
{
  "storeUrls": [
    "allbirds.com"
  ],
  "mode": "products",
  "collections": [],
  "maxProductsPerStore": 1000,
  "updatedSince": "",
  "includeVariants": true,
  "includeBodyHtml": false
}
```

# Actor output Schema

## `products` (type: `string`):

One row per product (type product, charged): title, vendor, type, tags, prices, compare-at prices, availability, variants, images and URL.

## `stores` (type: `string`):

Store rows (type store). status ok = analysed and charged (store/both mode). Blocked, headless, robots-disallowed, not-Shopify and invalid rows are free.

# 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 = {
    "storeUrls": [
        "allbirds.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("actor-forge/shopify-store-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 = { "storeUrls": ["allbirds.com"] }

# Run the Actor and wait for it to finish
run = client.actor("actor-forge/shopify-store-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 '{
  "storeUrls": [
    "allbirds.com"
  ]
}' |
apify call actor-forge/shopify-store-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,actor-forge/shopify-store-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/EB3NCiRtztAA0cwPk/builds/501f0dhegRuB7G7fp/openapi.json
