# Shopify Product Price & Catalog Scraper (`abdulwhab95/shopify-catalog-scraper`) Actor

Product and variant data from any Shopify store via the public /products.json endpoint. HTTP only, no browser, no proxy. Returns one row per variant (SKU) with its own price, compare-at price and availability — not one row per product.

- **URL**: https://apify.com/abdulwhab95/shopify-catalog-scraper.md
- **Developed by:** [ABDULWAHAB NASER RASHED ALQARAWI](https://apify.com/abdulwhab95) (community)
- **Categories:** E-commerce, Lead generation
- **Stats:** 2 total users, 1 monthly users, 50.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 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?

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

## Shopify Catalog & Price Scraper

Product and price data from **any Shopify store**, straight from the store's own public `/products.json` endpoint.

No browser. No proxy. No API key. Just clean rows.

***

### What you get

**One row per variant (SKU)** — because a size-8 shoe and a size-11 shoe have different prices and different stock, and price monitoring that collapses them is useless.

| Field | Example |
|---|---|
| `store` | `allbirds.com` |
| `title` | `Men's Strider Explore` |
| `vendor` | `Allbirds` |
| `variantTitle` | `8` |
| `sku` | `A11768M080` |
| `price` | `130.0` |
| `compareAtPrice` | `165.0` |
| `onSale` | `true` |
| `discountPct` | `21.21` |
| `available` | `false` |
| `productUrl` | `https://allbirds.com/products/...` |

Plus `productId`, `handle`, `productType`, `tags`, `publishedAt`, `updatedAt`, `imageUrl`, `optionNames`, `variantCount`, `variantId`, `grams`, `scrapedAt`.

**24 fields. Every one always present** — missing data comes back as `null`, never dropped. Pipe it straight into a database without defensive checks.

***

### Use it for

- **Competitor price monitoring** — schedule it daily, diff the `price` column
- **Sale and discount tracking** — filter `onSale = true`, sort by `discountPct`
- **Stock-out alerts** — watch `available` flip to `false`
- **Catalog research** — brands, product types, tags across a whole market
- **Feeding an LLM or agent** — the output is already flat, typed and clean

***

### Input

```json
{
  "storeDomains": ["allbirds.com", "kith.com", "deathwishcoffee.com"],
  "maxProductsPerStore": 250,
  "rowsPerVariant": true,
  "respectRobots": true,
  "requestDelayMs": 400
}
```

| Option | Default | What it does |
|---|---|---|
| `storeDomains` | — | Any Shopify store, with or without `https://` |
| `maxProductsPerStore` | 60 | Stop after N products per store |
| `rowsPerVariant` | `true` | Off = one row per product instead of per SKU |
| `respectRobots` | `true` | Skips any store whose `robots.txt` disallows the endpoint |
| `requestDelayMs` | 400 | Politeness delay. Lower it and stores start rate-limiting you |

***

### Speed and cost

A real run, four stores, 60 products each:

```
1,461 rows  ·  8 requests  ·  34 seconds
```

Because the endpoint returns 250 products in one request and each product carries its variants, **one request routinely yields thousands of rows**. That is why this Actor is cheap to run and fast to finish.

***

### Honest notes

**Currency is not returned.** Shopify's public endpoint does not carry a currency code, so `currency` is always `null`. Guessing it would be worse than leaving it empty.

**Not every store answers.** Some sit behind a WAF and return `403`, some rate-limit with `429`. The Actor records both in its run report instead of failing silently — check `blocked` and `rateLimited`, and `reachRate` for the share of stores that responded.

**Every run publishes a report** to the key-value store under `RUN_REPORT`: requests, rows, megabytes, reach rate, and the estimated cost per 1,000 rows.

**Public data only.** The Actor reads `robots.txt` before it reads anything else, and skips stores that disallow the endpoint. Reviewing a target store's own terms of use is still your call.

***

### Questions or a store that misbehaves?

Open an issue on the Actor page. Include the store domain — most problems are a single store's WAF, and they are usually quick to diagnose.

# Actor input Schema

## `storeDomains` (type: `array`):

One Shopify store per line: allbirds.com or https://kith.com

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

Stop after this many products per store. Each product yields one row per variant, so 250 products can be ~3,000 rows.

## `rowsPerVariant` (type: `boolean`):

On: a row per SKU with its own price (what price-monitoring buyers want). Off: a row per product.

## `respectRobots` (type: `boolean`):

Skip any store whose robots.txt disallows the endpoint. Keep this on.

## `requestDelayMs` (type: `integer`):

Politeness. Too low earns a 429 and a blocked store.

## `proxyConfiguration` (type: `object`):

Optional. Not needed for this endpoint - leave off unless a store rate-limits you.

## Actor input object example

```json
{
  "storeDomains": [
    "allbirds.com",
    "kith.com",
    "deathwishcoffee.com"
  ],
  "maxProductsPerStore": 60,
  "rowsPerVariant": true,
  "respectRobots": true,
  "requestDelayMs": 400,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Every scraped variant row.

## `runReport` (type: `string`):

Cost per 1,000 rows, publish verdict, and how many stores answered.

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

// Run the Actor and wait for it to finish
const run = await client.actor("abdulwhab95/shopify-catalog-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 = { "storeDomains": [
        "allbirds.com",
        "kith.com",
        "deathwishcoffee.com",
    ] }

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abdulwhab95/shopify-catalog-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/4rRd2gVbRWwnRZTra/builds/8a385crglN2sx4CgO/openapi.json
