# Shopify Store Products Scraper (`bercikgroup/shopify-store-products-scraper`) Actor

Extract the full product catalogue from any Shopify store - titles, variants, SKUs, prices, images and tags. No API key, no login.

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

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

Extract the **full product catalogue from any Shopify store** — titles, variants, SKUs, prices, compare-at prices, stock status, images and tags. No API key, no login, no store permission needed.

### What does Shopify Store Products Scraper do?

Every Shopify storefront publishes its catalogue at a public `/products.json` endpoint. This Actor reads it, walks the whole catalogue, and returns clean, structured records you can drop straight into a spreadsheet or database.

You get **one row per product** with a nested variants array, or **one row per variant** (SKU-level) if you're tracking prices. Point it at several competitors at once and it returns a single unified dataset across all of them.

Because it reads a public JSON endpoint rather than rendering pages, there's **no browser, no proxy and no CAPTCHA** — runs are fast and cheap.

### Why use Shopify Store Products Scraper?

- **Competitor price monitoring** — track a rival's entire catalogue on a schedule and see exactly what changed.
- **Assortment and gap analysis** — compare product types, vendors and price bands across several stores at once.
- **Dropshipping and reselling** — pull catalogues with SKUs, images and stock status ready for import.
- **Market research** — quantify how a category is priced across dozens of brands.
- **Stock monitoring** — watch which SKUs sell out and how quickly they return.
- **Lead generation for agencies** — profile a prospect's catalogue size and merchandising before a pitch.

### How to use Shopify Store Products Scraper

1. Click **Try for free**.
2. Add one or more **Shopify store URLs** — `allbirds.com` or `https://www.gymshark.com` both work.
3. Optionally filter by product type, vendor, tag, price range or stock status.
4. Turn on **One row per variant** if you want SKU-level rows for price tracking.
5. Set **Maximum results** to cap your spend.
6. Click **Start**, then download as **JSON, CSV, Excel, HTML or XML**.

### Input

```json
{
  "storeUrls": ["allbirds.com", "gymshark.com"],
  "productTypes": ["Shoes"],
  "minPrice": 50,
  "availableOnly": true,
  "oneRowPerVariant": false,
  "maxProductsPerStore": 1000,
  "maxResults": 5000
}
```

| Field | Type | Description |
| --- | --- | --- |
| `storeUrls` | array | Shopify stores — bare domain or full URL |
| `maxProductsPerStore` | integer | Stop after this many products per store |
| `maxResults` | integer | Hard cap on total records returned |
| `oneRowPerVariant` | boolean | SKU-level rows instead of product-level |
| `availableOnly` | boolean | Keep only in-stock items |
| `productTypes`, `vendors`, `tags` | array | Case-insensitive filters |
| `minPrice`, `maxPrice` | integer | Price bounds, in the store's own currency |

### Output

```json
{
  "storeDomain": "allbirds.com",
  "storeName": "Allbirds",
  "currency": "USD",
  "productId": 6842053460048,
  "title": "Men's Cruiser - Shadow Blue",
  "handle": "mens-cruiser-shadow-blue",
  "productUrl": "https://allbirds.com/products/mens-cruiser-shadow-blue",
  "vendor": "Allbirds",
  "productType": "Shoes",
  "tags": ["DNAM BRANDS", "EC STOCK"],
  "description": "A comfy everyday shoe made with merino wool.",
  "minPrice": 105,
  "maxPrice": 105,
  "available": true,
  "variantCount": 13,
  "variants": [
    {
      "variantId": 41990816759888,
      "title": "8",
      "sku": "A12856M080",
      "price": 105,
      "compareAtPrice": null,
      "currency": "USD",
      "available": true,
      "grams": 1000
    }
  ],
  "imageUrl": "https://cdn.shopify.com/...jpg",
  "imageCount": 4,
  "publishedAt": "2026-01-14T09:12:03-08:00"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

#### Data fields

| Field | Description |
| --- | --- |
| `storeDomain`, `storeName`, `currency` | Which store the row came from |
| `productId`, `title`, `handle`, `productUrl` | Product identity and link |
| `vendor`, `productType`, `tags` | Merchandising classification |
| `description` | Product description, HTML stripped |
| `minPrice`, `maxPrice`, `available` | Price range and stock across all variants |
| `variantCount`, `variants` | Every variant: SKU, price, compare-at price, options, weight |
| `imageUrl`, `imageCount`, `images` | Product imagery |
| `options` | Option names and values, e.g. Size / Colour |
| `publishedAt`, `createdAt`, `updatedAt` | Catalogue timestamps |

In **one row per variant** mode, each row carries the variant's own `sku`, `price` and `available` alongside the product context, and the nested `variants` array is dropped.

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

Priced **per record returned**, capped by **Maximum results** so you know your ceiling before the run starts. There's no browser and no proxy, so the underlying platform cost is very low.

A mid-sized catalogue is typically 200–500 products; large brands run into the thousands.

### Tips

- **Not every store exposes `/products.json`.** A minority disable it or run a custom storefront. The Actor logs a warning and moves on to the next store rather than failing the run.
- **`currency` and `storeName` come from `/meta.json`**, which custom storefronts don't serve. When it's unavailable both fields are `null` — prices are still correct, they're just in the store's own unstated currency.
- **Use `oneRowPerVariant` for price tracking**, product-level rows for catalogue analysis. Variant mode produces far more records, so raise `maxResults` accordingly.
- **Price filters behave sensibly in both modes.** At product level a product qualifies if any variant matches; in variant mode each row is filtered on its own price and stock.
- **`compareAtPrice` reveals discounting** — where it's higher than `price`, the item is on sale.
- **Schedule daily runs** and diff on `productId` + `sku` to build a price history.

### FAQ

**Do I need permission from the store?**
`/products.json` is a public endpoint that Shopify serves to anyone; it's the same data the storefront itself uses. This Actor requests it at a polite rate and reads nothing private — no customer data, no orders, no admin. That said, this is general information rather than legal advice; check your own obligations before redistributing catalogue data commercially.

**Why did a store return nothing?**
Either it isn't Shopify, or the merchant disabled the endpoint. The run log names the store and says so explicitly.

**Can I get inventory quantities?**
No. The public endpoint exposes whether a variant is available, not how many units remain. Exact stock counts require the merchant's own Admin API credentials.

**Can I scrape collections or a single product?**
This version walks the full catalogue. Filter the output by `productType`, `vendor` or `tags` to narrow it. If you need collection-level scraping, open an issue.

### Support

Found a bug or need a field that isn't here? Open an issue on the **Issues** tab and I'll take a look. Custom data pipelines and bespoke scraping work are available on request.

# Actor input Schema

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

One or more Shopify stores. Domain or full URL both work, e.g. "allbirds.com" or "https://www.gymshark.com".

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

Stop after scanning this many products in each store. Useful when comparing several large catalogues.

## `maxResults` (type: `integer`):

Hard cap on total records returned across all stores. You are charged per record.

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

Off: one row per product with a variants array. On: one row per variant (SKU-level), which is easier for price tracking but produces many more records.

## `availableOnly` (type: `boolean`):

Keep only products with at least one variant currently available.

## `productTypes` (type: `array`):

Keep only these product types, e.g. "Shoes", "Socks". Case-insensitive exact match.

## `vendors` (type: `array`):

Keep only products from these vendors. Case-insensitive exact match.

## `tags` (type: `array`):

Keep products carrying at least one of these tags. Case-insensitive.

## `minPrice` (type: `integer`):

Keep products with at least one variant priced at or above this value, in the store's own currency.

## `maxPrice` (type: `integer`):

Keep products with at least one variant priced at or below this value, in the store's own currency.

## Actor input object example

```json
{
  "storeUrls": [
    "allbirds.com"
  ],
  "maxProductsPerStore": 1000,
  "maxResults": 5000,
  "oneRowPerVariant": false,
  "availableOnly": false
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

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

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

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

```

## MCP server setup

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