# Shopify & WooCommerce Products Scraper (`teddythebuilder/shopify-products-scraper`) Actor

Scrape full product catalogues from any Shopify or WooCommerce store: titles, prices, compare-at prices, variants, SKUs, stock, images, tags. Monitor mode returns only new, changed and removed products. No login, no browser. Export JSON/CSV or call via API/MCP.

- **URL**: https://apify.com/teddythebuilder/shopify-products-scraper.md
- **Developed by:** [Teddy Wasserman](https://apify.com/teddythebuilder) (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 $1.10 / 1,000 product returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 & WooCommerce Products Scraper do?

**Shopify & WooCommerce Products Scraper** extracts complete product catalogues from any Shopify or WooCommerce store. Give it store URLs and you get **one clean row per product** (or per variant) with title, vendor or brand, product type, tags, categories, price, compare-at price, discount, stock status, variants with SKUs, images and timestamps.

It reads the stores' own public product feeds: Shopify's storefront `products.json` and the WooCommerce Store API. That makes it fast and reliable. There is no browser, no HTML parsing and no login, and the platform is **detected automatically**. A 1,000-product catalogue usually takes under a minute and costs about **$2**.

Turn on **monitor mode** and schedule it daily: the actor remembers each store's catalogue and returns **only new products, price changes, stock changes and removed products**. Unchanged products are not output and cost only $0.05 per 1,000.

Typical uses:

- **Competitor price monitoring:** track the prices, discounts and sell-outs of competing DTC brands every morning.
- **Product research and dropshipping:** pull full catalogues of trending stores into a spreadsheet and sort by price, vendor or launch date.
- **Catalogue migration and feeds:** export a store's products (yours or a client's) to CSV, JSON or Excel.
- **Market and pricing analysis:** compare price points, discount depth and assortment across dozens of stores in one dataset.
- **Restock alerts:** get notified when a sold-out product or size comes back in stock.

### Why use Shopify & WooCommerce Products Scraper?

- **Two platforms, one schema.** Shopify and WooCommerce products come out with the same field names (`price`, `compareAtPrice`, `available`, `vendor`, `categories`...). You can mix stores from both platforms in one run.
- **Auto-detection.** Paste a store URL; the actor finds out whether it runs Shopify or WooCommerce and which product API it exposes, including WooCommerce sites without pretty permalinks.
- **Built-in change monitoring.** Other tools make you diff two exports yourself or buy a separate tracker. Here a single checkbox gives you `new`, `price_changed`, `stock_changed` and `removed` rows, with the old and new values.
- **Product or variant rows.** Keep variants nested in one product row, or switch to one row per size/colour with its own price, SKU and stock flag, ideal for CSV and price tracking.
- **Fair pricing, proxies included.** $2 per 1,000 rows with volume discounts on higher Apify plans. Residential proxies are included at no extra cost, stores that fail are **free**, and unchanged products in monitor mode cost $0.05 per 1,000.
- **Polite and robust.** Pages of one store are fetched one at a time, with automatic back-off on rate limits (HTTP 429) and retries on server errors.
- **API and AI-agent ready.** Run it from Make, Zapier or n8n, call it via the Apify API, or let an AI agent use it through the Apify MCP server.

### What data can you extract?

| Field | Example | Description |
|---|---|---|
| `store` | `https://www.allbirds.com` | Store base URL (after redirects) |
| `platform` | `shopify` | `shopify` or `woocommerce` |
| `storeName` | `Allbirds` | Store name from the store's metadata |
| `currency` | `USD` | Store currency |
| `productId` | `7205191516240` | Platform product ID |
| `handle` | `womens-cruiser-canvas-auburn` | Product handle (Shopify) or slug (WooCommerce) |
| `url` | `https://www.allbirds.com/products/...` | Product page URL |
| `title` | `Women's Cruiser Canvas - Auburn` | Product title |
| `vendor` | `Allbirds` | Shopify vendor or WooCommerce brand |
| `productType` | `Shoes` | Shopify product type, or WooCommerce type (`simple`, `variable`...) |
| `categories` | `["Sale"]` | WooCommerce categories, or the Shopify collection you scraped |
| `tags` | `["womens", "canvas"]` | Product tags |
| `description` | `Classic court style...` | Description as plain text (optional) |
| `sku` | `A12438W050` | SKU (for single-variant products and variant rows) |
| `price` | `75.0` | Lowest current price |
| `priceMax` | `95.0` | Highest variant price |
| `compareAtPrice` | `110.0` | Original price when the product is discounted |
| `onSale` | `true` | Whether any variant is discounted |
| `discountPercent` | `30.0` | Discount of the cheapest variant |
| `available` | `true` | In stock (at least one variant available) |
| `stockStatus` | `in-stock` | WooCommerce stock class (`in-stock`, `out-of-stock`, `on-backorder`) |
| `variantsCount` / `variantsAvailable` | `13` / `5` | Number of variants and how many are in stock |
| `options` | `[{"name": "Size", "values": ["5", "6"]}]` | Option names and values |
| `variants` | `[{"variantId": ..., "sku": ..., "price": ..., "available": ...}]` | Variant list (product mode) |
| `imageUrl` / `images` | `https://cdn.shopify.com/...` | Main image and all image URLs |
| `rating` / `reviewCount` | `4.6` / `128` | Average rating and review count (WooCommerce) |
| `createdAt` / `publishedAt` / `updatedAt` | `2026-09-25T15:55:13-07:00` | Shopify timestamps |
| `changeType` / `changes` | `price_changed` / `[{"field": "price", "old": 95, "new": 75}]` | Monitor mode only |
| `scrapedAt` | `2026-10-13T12:00:00Z` | When the row was collected |

In **variant mode** each row also has `variantId`, `variantTitle`, `option1`–`option3`, `grams`, `requiresShipping` and `variantImageUrl`, and `price`, `compareAtPrice`, `sku` and `available` refer to that variant.

### How to use Shopify & WooCommerce Products Scraper (step by step)

1. Click **Try for free** (or **Start**) on this page. A free Apify account is enough.
2. Paste one or more **store URLs**, e.g. `https://www.allbirds.com`. You can also paste a collection URL (`/collections/sale`), a WooCommerce category URL (`/product-category/shoes/`) or a single product URL.
3. Set **Max products per store**. Use a large number such as 100000 to read the whole catalogue.
4. Choose **One row per**: *Product* (variants nested) or *Variant* (one row per size or colour).
5. Optional: turn on **Monitor mode** and give it a **Monitor ID**, then add a daily **schedule** in Apify Console.
6. Click **Start**, then download the results as JSON, CSV, Excel or HTML, or connect them to Google Sheets, Make, Zapier or n8n.

### Input example

```json
{
  "startUrls": [
    "https://www.allbirds.com",
    "https://kith.com/collections/footwear",
    "https://woocommerce.com"
  ],
  "maxProductsPerStore": 500,
  "outputLevel": "product",
  "monitorChanges": false,
  "onlyAvailable": false,
  "onlyOnSale": false,
  "includeDescription": true
}
```

### Output example

```json
[
  {
    "store": "https://www.allbirds.com",
    "platform": "shopify",
    "storeName": "Allbirds",
    "currency": "USD",
    "productId": 7234399830096,
    "handle": "mens-cruiser-tweed-hazy-indigo",
    "url": "https://www.allbirds.com/products/mens-cruiser-tweed-hazy-indigo",
    "title": "Men's Cruiser Tweed - Hazy Indigo (Light Grey Sole)",
    "vendor": "Allbirds",
    "productType": "Shoes",
    "price": 77.0,
    "priceMax": 77.0,
    "compareAtPrice": 110.0,
    "onSale": true,
    "discountPercent": 30.0,
    "available": false,
    "variantsCount": 13,
    "variantsAvailable": 0,
    "options": [{"name": "Size", "values": ["8", "8.5", "9", "9.5", "10"]}],
    "variants": [{"variantId": 41393834950736, "variantTitle": "8", "sku": "A11586M080", "price": 77.0, "compareAtPrice": 110.0, "available": false}],
    "imageUrl": "https://cdn.shopify.com/s/files/1/1104/4168/files/....png",
    "publishedAt": "2026-09-25T16:50:18-07:00",
    "scrapedAt": "2026-10-13T12:05:00Z"
  },
  {
    "store": "https://woocommerce.com",
    "platform": "woocommerce",
    "storeName": "WooCommerce",
    "currency": "USD",
    "productId": 18734003307187,
    "handle": "fortis-payments",
    "url": "https://woocommerce.com/products/fortis-payments/",
    "title": "Fortis Payments",
    "productType": "simple",
    "categories": ["WooCommerce extensions", "Official payments", "Processors & gateways", "B2B payments"],
    "sku": "W00O18734003307187",
    "price": 0.0,
    "onSale": false,
    "available": true,
    "stockStatus": "in-stock",
    "rating": 2.75,
    "reviewCount": 4,
    "scrapedAt": "2026-10-13T12:05:00Z"
  }
]
```

A monitor-mode row looks the same, plus `"changeType": "price_changed"` and `"changes": [{"field": "price", "old": 95.0, "new": 77.0}]`. Removed products come back as a short row with `"changeType": "removed"` and their last known title, price and URL.

You can export the dataset as JSON, CSV, Excel, XML or HTML. For CSV and Excel, **variant mode** gives the flattest table.

### How much does it cost?

The actor uses **pay-per-event** pricing, so you pay only for rows you receive:

| Event | Price |
|---|---|
| Actor start | $0.0005 per run |
| Product returned | $0.002 per row ($2 per 1,000 rows) |
| Stores that fail (not Shopify/WooCommerce, blocked, invalid URL) | free |
| Unchanged product checked (monitor mode only, not output) | $0.00005 per product ($0.05 per 1,000) |
| Residential proxy traffic | included |

In variant mode each variant row counts as one row. Higher Apify plans get automatic volume discounts (Bronze −15%, Silver −30%, Gold and above −45%).

Worked examples:

- **Full catalogue of a 700-product store:** 700 × $0.002 ≈ **$1.40**.
- **Daily price monitoring of 10 competitor stores with 500 products each:** the first run is about $10. After that you pay mainly for changes: if 3% of products change per day, that is 150 rows × $0.002 + 4,850 unchanged × $0.00005 ≈ **$0.54 per day, or about $16 per month**.
- **Weekly variant-level export of a 200-product store with 8 sizes each:** 1,600 rows ≈ $3.20 per run ≈ **$13 per month**.

Platform compute and proxy traffic are included in these prices; you pay nothing extra. Use **Max rows in total** as a hard cost cap.

### Use cases

- **DTC brands and e-commerce managers:** watch competitors' prices, new launches and discount campaigns, and react the same day.
- **Dropshippers and product researchers:** pull complete catalogues of successful stores, then sort by launch date, price or vendor to spot winning products.
- **Pricing and market-intelligence agencies:** build price indices across dozens of Shopify and WooCommerce stores with one consistent schema.
- **Developers and data teams:** feed product data into BI dashboards, search indexes or ML pipelines through the API.
- **Agencies migrating stores:** export a client's existing catalogue (titles, variants, SKUs, images) as the starting point for a migration.
- **AI agents:** answer "what does store X sell and at what price?" or "which products went on sale this week?" with structured data instead of web browsing.

### Use with AI agents, MCP and the API

Run it from the command line with curl (replace `YOUR_TOKEN`):

```bash
curl -X POST "https://api.apify.com/v2/acts/teddythebuilder~shopify-products-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"startUrls": ["https://www.allbirds.com"], "maxProductsPerStore": 50, "onlyOnSale": true}'
```

Or from Python with the official client:

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_TOKEN")
run = client.actor("teddythebuilder/shopify-products-scraper").call(run_input={
    "startUrls": ["https://www.allbirds.com", "https://woocommerce.com"],
    "maxProductsPerStore": 1000,
    "monitorChanges": True,
    "monitorId": "competitors",
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item.get("changeType"), item.get("title"), item.get("price"))
```

AI agents (Claude, ChatGPT, Cursor and others) can call this actor through the **Apify MCP server** at `https://mcp.apify.com`. Add `teddythebuilder/shopify-products-scraper` to the server's actor list and the agent can fetch a store's products or its latest price changes on demand.

### Integrations

- **Google Sheets:** send each run's products to a sheet with the Google Sheets integration, for a live competitor price list.
- **Make, Zapier and n8n:** trigger a scenario when a run finishes, e.g. post `price_changed` rows to Slack or create tasks for restocked products.
- **Webhooks:** call your own endpoint when a run succeeds and fetch the dataset from there.
- **Schedules:** run it hourly, daily or weekly from Apify Console. Monitor mode is designed for this.

### Data source and legality

The actor reads the same public product feeds that the stores' own websites and themes use:

- **Shopify:** the public storefront JSON endpoints `/products.json`, `/collections/<handle>/products.json`, `/products/<handle>.json` and `/meta.json` (for the store name and currency). These are not disallowed in Shopify's default robots.txt.
- **WooCommerce:** the public, unauthenticated **WooCommerce Store API** (`/wp-json/wc/store/v1/products`), which block-based themes use to render the shop.

It collects **product information only**: no customer data, no orders, no reviews with reviewer names and no personal data. Requests are made one page at a time per store (250 Shopify or 100 WooCommerce products per request) through Apify residential proxies, and slow down automatically when a store answers with "too many requests". You are responsible for how you use the data, including respecting each store's terms and intellectual property (for example, product images and descriptions are the store's copyright).

### FAQ

**Which stores work?**
Most Shopify stores and most WooCommerce stores on WooCommerce 5+ work out of the box. Some stores disable these feeds, run a headless front end (Shopify Hydrogen, custom React shops) or sit behind bot protection. Those come back as an error row, which is free.

**Can I get exact inventory quantities?**
No. Shopify's public feed shows whether each variant is *available*, not how many units are left. WooCommerce shows the stock status and, if the store enables it, `lowStockRemaining`.

**Does it include WooCommerce variation prices?**
Variable WooCommerce products show the price range (`price` to `priceMax`) and the list of variations with their attributes. Per-variation prices are not in the Store API listing.

**How does monitor mode work?**
After each run the actor saves a compact snapshot of the catalogue (per store, collection and Monitor ID) in your Apify account. The next run compares against it. Removed products are only reported when the whole catalogue was read, so set **Max products per store** high enough.

**Why does it use residential proxies?**
Shopify's edge network rate-limits requests from shared cloud and datacenter IP ranges (HTTP 429), including Apify's. Residential IPs avoid that. The proxy traffic is small (about 0.5 MB per 1,000 products) and its cost is included in the price. You can switch to your own proxies in the Proxy section.

**How fresh is the data?**
It is live: every run reads the store at that moment.

**Does it work on the free Apify plan?**
Yes. The default test run (10 products from two stores) costs about $0.04, well within the monthly free credits.

**Can I scrape only one collection or category?**
Yes. Paste the collection URL (Shopify, e.g. `/collections/sale`) or category URL (WooCommerce, e.g. `/product-category/shoes/`) instead of the home page.

**I need another field or platform.**
Open an issue on the Issues tab. Requests that many users need are usually shipped within a week. If the actor saves you time, a short review on this page helps other users find it.

### Related actors

- [Tech Stack Detector](https://apify.com/teddythebuilder/tech-stack-detector): find out which sites run Shopify or WooCommerce (plus their apps, analytics and CDN), then feed them into this actor.
- [Website SEO Audit Crawler](https://apify.com/teddythebuilder/website-seo-audit): audit a store's pages for broken links, missing titles, noindex and sitemap gaps.
- [Domain WHOIS & DNS API](https://apify.com/teddythebuilder/domain-whois-dns-api): domain age, registrar, email provider and SSL expiry for a list of store domains.
- [Career Site Jobs API](https://apify.com/teddythebuilder/career-site-jobs-api): see who an e-commerce brand is hiring, straight from its career site.

### Changelog and support

- **1.0 (2026-10):** first release. Shopify and WooCommerce with auto-detection, store/collection/category/product URLs, product or variant rows, on-sale and in-stock filters, and monitor mode with new/price/stock/removed changes.

Questions, bugs or a store that doesn't work? Open an issue. We reply within 24 hours.

# Actor input Schema

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

Shopify or WooCommerce store URLs, e.g. https://www.allbirds.com. Collection (/collections/sale), category (/product-category/shoes) and product URLs are also accepted. The platform is detected automatically.

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

Stop after this many products per URL. Set it high (e.g. 100000) to read the whole catalogue.

## `outputLevel` (type: `string`):

Product: one row per product with a nested variants list. Variant: one row per Shopify variant (size/colour) with its own price, SKU and stock flag, best for price monitoring and CSV export.

## `monitorChanges` (type: `boolean`):

Remember each store's catalogue between runs and output only new products, price changes, stock changes and removed products. Unchanged products are not output and cost only $0.05 per 1,000. The first run outputs everything as 'new'.

## `monitorId` (type: `string`):

Name of the saved snapshot, e.g. 'competitor-prices'. Use different IDs for independent schedules that watch the same store.

## `includeRemoved` (type: `boolean`):

Output a 'removed' row for products that disappeared since the last run. Only reported when the whole catalogue was read.

## `onlyAvailable` (type: `boolean`):

Skip products (or variants) that are sold out.

## `onlyOnSale` (type: `boolean`):

Keep only products with a compare-at (regular) price above the current price.

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

Add the product description as plain text (HTML removed, max 5,000 characters).

## `includeImages` (type: `boolean`):

Add the list of all product image URLs. The main image URL is always included.

## `platform` (type: `string`):

Leave on auto-detect unless a store is misdetected.

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

Hard cap on output rows across all stores (0 = no cap). Useful as a cost limit.

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

How many stores are read at the same time (pages within one store are always read one by one).

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

Residential proxy is used by default because Shopify rate-limits shared cloud and datacenter IPs. The proxy cost is included in the price. If you pick your own proxies, the IP changes automatically when a store answers 403 or 429.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.allbirds.com",
    "https://woocommerce.com"
  ],
  "maxProductsPerStore": 10,
  "outputLevel": "product",
  "monitorChanges": false,
  "monitorId": "default",
  "includeRemoved": true,
  "onlyAvailable": false,
  "onlyOnSale": false,
  "includeDescription": true,
  "includeImages": true,
  "platform": "auto",
  "maxResults": 0,
  "maxConcurrency": 4,
  "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://woocommerce.com"
    ],
    "maxProductsPerStore": 10,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("teddythebuilder/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 = {
    "startUrls": [
        "https://www.allbirds.com",
        "https://woocommerce.com",
    ],
    "maxProductsPerStore": 10,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("teddythebuilder/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 '{
  "startUrls": [
    "https://www.allbirds.com",
    "https://woocommerce.com"
  ],
  "maxProductsPerStore": 10,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call teddythebuilder/shopify-products-scraper --silent --output-dataset

```

## MCP server setup

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