# Shopify & WooCommerce Product Scraper: Prices, Stock (`datagleaner/shopify-product-scraper`) Actor

Scrape every product of any Shopify or WooCommerce store: price, compare-at price, currency, variants with SKU and stock, images, tags, categories and vendor. Whole stores, Shopify collections or single products, no browser. $0.40 per 1,000 products.

- **URL**: https://apify.com/datagleaner/shopify-product-scraper.md
- **Developed by:** [Data Gleaner](https://apify.com/datagleaner) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.40 / 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

## Shopify & WooCommerce Product Scraper: Prices, Stock

**Shopify & WooCommerce Product Scraper** exports the full product catalog of any Shopify or WooCommerce store into a clean table. Give it store addresses, such as `allbirds.com` or `https://kaffeeroester.de`. For each product you get the **title, current price and compare-at (original) price, currency, every variant with its SKU, price and stock status**, option values (size, color), all image URLs, tags, categories, vendor, description, and the dates it was created, updated and published. Shopify **collection URLs** and **single product URLs** work too, and the platform is detected for you. It reads the catalog JSON that each store publishes for its own storefront, so there is no browser and no login. It costs **$0.40 per 1,000 products**, with no start fee.

### What you can do with it

- **Monitor competitor prices.** Run a list of rival stores every day or week and compare `price`, `compareAtPrice` and `onSale` over time. Every row has `updatedAt` from the store and `scrapedAt` from the run.
- **Track stock and restocks.** `available` per product and per variant shows which sizes and colors are sold out.
- **Product research and dropshipping.** Pull whole catalogs of successful stores: what they sell, at what prices, which vendors, how many variants, and what they launched recently (`createdAt`, `publishedAt`).
- **Catalog migration and feeds.** Export a store's products with images, options, SKUs and descriptions to move them to another platform or build a product feed.
- **Market and brand analysis.** Count products, price bands and vendors across hundreds of stores in one dataset.
- **Data for AI agents and apps.** The same field names for Shopify and WooCommerce, ready for a spreadsheet, a database or an LLM.

### Input

| Field | Type | What it does |
|---|---|---|
| `startUrls` | list of text | Store home pages or bare domains (whole catalog), Shopify collection URLs such as `https://www.allbirds.com/collections/mens` (that collection), or Shopify product URLs (that product). One per line. |
| `maxProductsPerStore` | number | Default 1,000, max 100,000. Each store URL stops after this many products. |
| `maxConcurrency` | number | How many store URLs run at once. Default 5, max 10. Pages within one store are fetched one after another. |
| `requestDelaySecs` | number | Pause between two pages of the same store. Default 0.5 seconds. |
| `proxyConfiguration` | proxy | Default: Apify residential proxy, included in the price. See Limits. |

Example:

```json
{
  "startUrls": [
    "https://www.allbirds.com",
    "https://kith.com/collections/mens-footwear",
    "https://kaffeeroester.de"
  ],
  "maxProductsPerStore": 2000
}
```

An empty input `{}` runs a small example (the first 5 products of allbirds.com), and the status message says so.

### Output

One row per product. Example (shortened lists):

```json
{
  "platform": "shopify",
  "storeUrl": "https://allbirds.com",
  "storeName": "Allbirds",
  "productId": "7340901859408",
  "title": "Women's Allbirds Flip Flop - Dusty Pink",
  "handle": "womens-allbirds-flip-flop-dusty-pink",
  "url": "https://allbirds.com/products/womens-allbirds-flip-flop-dusty-pink",
  "vendor": "Allbirds",
  "productType": "Shoes",
  "categories": [],
  "tags": ["allbirds::gender => womens", "allbirds::material => sugar"],
  "description": "Sun on your feet. Comfort underneath. Light, easy, and made for warm weather, these flip flops...",
  "price": 25,
  "maxPrice": 25,
  "compareAtPrice": 50,
  "currency": "USD",
  "onSale": true,
  "available": true,
  "sku": "A12513W050",
  "variantCount": 7,
  "variants": [
    {"variantId": "42146889039952", "title": "5", "sku": "A12513W050", "price": 25, "compareAtPrice": 50,
     "available": false, "options": {"Size": "5"}, "weightGrams": 455}
  ],
  "options": [{"name": "Size", "values": ["5", "6", "7", "8", "9", "10", "11"]}],
  "imageUrl": "https://cdn.shopify.com/s/files/1/1104/4168/files/A12513_26Q2_Allbirds-Flip-Flop-Dusty-Pink_PDP_LEFT.png?v=1774646345",
  "images": ["https://cdn.shopify.com/s/files/1/1104/4168/files/A12513_26Q2_Allbirds-Flip-Flop-Dusty-Pink_PDP_LEFT.png?v=1774646345"],
  "rating": null,
  "reviewCount": null,
  "createdAt": "2026-03-27T14:03:50-07:00",
  "updatedAt": "2026-10-21T17:18:34-07:00",
  "publishedAt": "2026-09-25T16:58:13-07:00",
  "startUrl": "https://www.allbirds.com",
  "scrapedAt": "2026-10-22T10:15:02+00:00"
}
```

| Field | What it holds |
|---|---|
| `platform`, `storeUrl`, `storeName` | `shopify` or `woocommerce`, the store address, and the Shopify store name. |
| `productId`, `handle`, `url`, `title` | The store's product id, URL slug, product page and title. |
| `price`, `maxPrice`, `currency` | Lowest and highest current variant price, as numbers, and the ISO currency code. |
| `compareAtPrice`, `onSale` | The original price before the sale (cheapest variant), and whether any variant is discounted. |
| `available` | True when at least one variant can be bought. |
| `sku`, `variantCount`, `variants` | First SKU, number of variants, and each variant's id, title, SKU, price, compare-at price, availability, option values and weight. |
| `options` | Option names and their values, e.g. Size: 5 to 12. |
| `vendor`, `productType`, `categories`, `tags` | Brand or vendor, product type, WooCommerce categories, and tags. |
| `description` | The product description as plain text. |
| `imageUrl`, `images` | Main image and every image URL. |
| `rating`, `reviewCount` | Average rating and review count, where the WooCommerce store has reviews. |
| `createdAt`, `updatedAt`, `publishedAt` | Shopify's product dates (ISO 8601). |
| `startUrl`, `scrapedAt` | The input URL the row came from, and when it was collected. |

Per-store results (platform, products found, and a reason for any store that returned nothing) are saved in the run's key-value store as the record `STORES`.

Fill rates measured on Apify over 17,003 products from 38 stores (2026-10-22). Shopify (16,173 products, 31 stores): `title`, `price`, `currency`, `available`, `url`, `vendor`, `createdAt` 100%; `imageUrl` 99%; `sku` 98%; `description` 95%; `productType` 92%. WooCommerce (830 products, 7 stores): `title`, `price`, `currency`, `available`, `url` 100%; `categories` 97%; `imageUrl` 96%; `description` 95%; `sku` 21%, as many stores leave it empty. `compareAtPrice` is filled only for products on sale (26% of Shopify rows, 10% of WooCommerce rows in these runs).

Shopify vs WooCommerce: WooCommerce stores publish variant ids and options but not each variant's own price, SKU or stock, so those variant fields are empty there; the product-level price range, stock status and SKU are filled. WooCommerce has no public product dates.

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

You pay per product saved to the dataset. This price is final:

| Event | Price | Per 1,000 |
|---|---|---|
| `product`: one product row (all its variants included) | $0.0004 | $0.40 |

There is no start fee. Nothing is charged for failed requests, retries, repeated products or stores that return nothing. Platform usage and the residential proxy are included in the price. The run stops by itself when it reaches your **maximum total charge**.

Examples:

- **One store with 600 products:** **$0.24**.
- **Daily price check of 10 rival stores** with 500 products each, for a month: 150,000 products = **$60**.
- **A 3,000-product catalog export:** **$1.20**.

### Limits

- **Shopify and WooCommerce only.** Other platforms are reported in the status message as "not a Shopify or WooCommerce store". A few large Shopify brands run a custom front end that turns off the public catalog; for `www.` addresses the Actor also tries the bare domain (and the other way round), which recovers some of them.
- **Stores behind a bot check** are skipped and listed in the status message. The Actor never tries to get past a check a store has put up.
- **Speed.** Shopify serves 250 products per request and WooCommerce 100. On Apify, 30 Shopify stores (8,978 products) took 85 seconds, and 6,000 products from two big stores 89 seconds.
- **Proxy.** Shopify rate-limits catalog requests from shared datacenter IPs (most requests were refused in our tests), so the default is Apify's residential proxy, and every retry uses a new IP. You can switch to another proxy or none in `proxyConfiguration`.
- **Prices** are the store's own list prices in its base currency, as its catalog publishes them; they do not include taxes, shipping or local-market price rules.
- **Collections and single products** are supported for Shopify. For WooCommerce, give the store address; the whole catalog is returned.

### Use with Python

```python
## pip install apify-client
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("datagleaner/shopify-product-scraper").call(
    run_input={"startUrls": ["https://www.allbirds.com"], "maxProductsPerStore": 500}
)
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item["title"], item["price"], item["compareAtPrice"], item["available"])
```

That run returns up to 500 products for at most $0.20.

### Use with JavaScript / Node.js

```js
// npm install apify-client
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('datagleaner/shopify-product-scraper').call({
    startUrls: ['https://kith.com/collections/mens-footwear', 'https://kaffeeroester.de'],
    maxProductsPerStore: 300,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const p of items) console.log(p.platform, p.title, p.price, p.currency);
```

### Use it from n8n, Make, Zapier or an AI agent

Actor ID: `datagleaner/shopify-product-scraper`

Minimal input:

```
{"startUrls": ["https://www.allbirds.com"], "maxProductsPerStore": 50}
```

Each tool below runs this Actor with your own Apify API token.

- **n8n:** add the **Apify** node (`@apify/n8n-nodes-apify`) and choose **Run an Actor and get dataset**. Set the Actor to `datagleaner/shopify-product-scraper` and paste the input above.
- **Make:** use the Apify app's **Run an Actor** module, then **Get Dataset Items**.
- **Zapier:** use the Apify action **Run Actor**, then the search **Fetch dataset items**.
- **Scheduled monitoring:** save the input as a task in Apify Console and add a schedule (daily or weekly) to collect fresh prices and stock.
- **AI agents (MCP):** connect to `https://mcp.apify.com?tools=datagleaner/shopify-product-scraper`. In Claude Code:

  ```
    claude mcp add --transport http apify "https://mcp.apify.com?tools=datagleaner/shopify-product-scraper"
  ```

  Then run `/mcp` to sign in to Apify, and ask in plain language. For example: "Use the Shopify product scraper on allbirds.com and list the products on sale with their discount."

### FAQ

**How do I scrape all products from a Shopify store?** Put the store address in `startUrls` (for example `allbirds.com`) and set `maxProductsPerStore` above the store's size. The Actor pages through the whole catalog, 250 products per request.

**Can I scrape one Shopify collection?** Yes. Use the collection URL, such as `https://www.allbirds.com/collections/mens`.

**Does it work for WooCommerce?** Yes. Give the store address; the Actor detects WooCommerce and reads its public Store API catalog, with prices, sale prices, stock status, categories, attributes and images.

**How do I know if a store runs Shopify or WooCommerce?** You don't need to. Mix both in one list; each row says its `platform`, and the `STORES` record lists what was found for each URL.

**Do I get inventory quantities?** Stores publish whether each variant can be bought (`available`), not how many units are left, so the Actor returns availability.

**Can I track price changes over time?** Yes. Schedule the same input daily and compare runs by `productId` (and `variantId` for each size or color).

**Need store emails, phones and social links instead?** Our Shopify Email Scraper (`datagleaner/shopify-store-contacts`) returns each store's public contact details.

**Do I need a Shopify account, API key or proxy?** No. Everything runs on Apify. You only need an Apify account.

### Responsible use

This Actor collects only product data that stores publish openly for their own storefronts: products, prices, images and descriptions. It does not log in, does not read customer data, and skips any store that shows a bot check. Product descriptions and images belong to their owners, so check your rights before you republish them. **You** are responsible for how you use the results and for any rules that apply where you work. This is not legal advice.

### Feedback

If this Actor saved you time, a rating on its Store page helps others find it. Problems or requests: open an issue on the Issues tab.

# Actor input Schema

## `startUrls` (type: `array`):

One per line. A store's home page or bare domain (allbirds.com) returns the whole catalog; a Shopify collection URL (https://www.allbirds.com/collections/mens) returns that collection; a Shopify product URL returns that product. The platform is detected for you. One row per product.

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

Stop each store URL after this many products. Shopify serves 250 products per request and WooCommerce 100, so a 5,000-product store takes about 20 requests.

## `maxConcurrency` (type: `integer`):

How many store URLs are fetched at once, up to 10. Pages within one store are always fetched one after another.

## `requestDelaySecs` (type: `number`):

Polite pause between two pages of the same store.

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

Shopify rate-limits catalog requests from shared datacenter IPs, so the default is Apify's residential proxy, included in the price. Each retry uses a new IP.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.allbirds.com",
    "https://kaffeeroester.de"
  ],
  "maxProductsPerStore": 10,
  "maxConcurrency": 5,
  "requestDelaySecs": 0.5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (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 = {
    "startUrls": [
        "https://www.allbirds.com",
        "https://kaffeeroester.de"
    ],
    "maxProductsPerStore": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("datagleaner/shopify-product-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 = {
    "startUrls": [
        "https://www.allbirds.com",
        "https://kaffeeroester.de",
    ],
    "maxProductsPerStore": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("datagleaner/shopify-product-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 '{
  "startUrls": [
    "https://www.allbirds.com",
    "https://kaffeeroester.de"
  ],
  "maxProductsPerStore": 10
}' |
apify call datagleaner/shopify-product-scraper --silent --output-dataset

```

## MCP server setup

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