# Shopify Product Scraper (`electrabot.info/shopify-product-scraper`) Actor

Extract every product from any Shopify store: titles, prices, variants, stock, images, tags. Automatic whole-catalog pagination, four fallback extraction methods, honest failure reporting, no browser. Export to Excel, CSV, or JSON. Pay per result - you only pay for products delivered.

- **URL**: https://apify.com/electrabot.info/shopify-product-scraper.md
- **Developed by:** [electra bot](https://apify.com/electrabot.info) (community)
- **Categories:** SEO tools, E-commerce, Developer tools
- **Stats:** 1 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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 Product Scraper

Extract the **full product catalog** from almost any public **Shopify** store — titles,
descriptions, vendors, product types, tags, images, and every variant (price,
compare-at price, SKU, availability) — and download the results as Excel, CSV, or JSON.

No code required. Paste a store address, click Start, done.

**Pay per result** — you're only charged for products actually scraped, never for
failed or empty runs.

---

### What can I use it for?

- **Competitor & market research** — pull a rival store's entire catalog with prices and stock status in minutes.
- **Price monitoring** — schedule runs and track price / compare-at-price changes over time.
- **Dropshipping & sourcing** — evaluate a supplier's assortment, variants, and availability before committing.
- **Catalog migration & syncing** — export a complete, structured product feed from any Shopify storefront.
- **Feed building** — generate product feeds for ads, affiliate sites, or search indexes.

---

### Input

| Field | Required | Description |
|-------|----------|-------------|
| **Store URL or handle** | ✅ | Any of: a myshopify handle (`bajaao`), a custom domain (`tentree.com`), or a full URL (`https://www.allbirds.com`) |
| **Max items** | – | Maximum products to collect. **Leave empty (or 0) to scrape the entire store catalog.** Set e.g. `500` to stop early. |
| **Starting page** (advanced) | – | Override the starting catalog page. Leave at 1. |
| **Proxy configuration** | – | **Off by default — most stores don't need it.** Enable Apify Proxy (datacenter is enough) only if a store rate-limits you; residential only as a last resort. |

### Output

One dataset record per product. Example (shortened):

```json
{
  "id": 4808578760765,
  "title": "Men's Tree Runners",
  "handle": "mens-tree-runners",
  "description": "Light, breathable everyday sneakers made from eucalyptus tree fiber.",
  "vendor": "Allbirds",
  "productType": "Shoes",
  "tags": ["men", "sneakers", "tree"],
  "publishedAt": "2024-03-12T09:00:01-07:00",
  "options": [{ "name": "Size", "position": 1, "values": ["8", "9", "10"] }],
  "images": [
    { "src": "https://cdn.shopify.com/s/files/1/.../TR1MBBW.png",
      "width": 1600, "height": 1600, "position": 1, "variantIds": [] }
  ],
  "variants": [
    {
      "id": 32924009496637,
      "title": "8",
      "sku": "TR1MBBW080",
      "price": "98.00",
      "compareAtPrice": null,
      "available": true,
      "option1": "8", "option2": null, "option3": null,
      "grams": 340,
      "barcode": null,
      "requiresShipping": true,
      "taxable": true,
      "position": 1,
      "featuredImage": null
    }
  ],
  "url": "https://allbirds.com/products/mens-tree-runners",
  "createdAt": "2024-03-10T11:02:44-07:00",
  "updatedAt": "2026-07-01T02:14:09-07:00",
  "source": "products.json"
}
````

#### Product-level fields

| Field | Description |
|-------|-------------|
| `title` | Product name |
| `handle` | Shopify URL slug |
| `description` | Plain-text description (HTML stripped, entities decoded) |
| `vendor` | Brand / vendor |
| `productType` | Shopify product type |
| `tags` | List of tag strings |
| `publishedAt` | ISO timestamp of when the product was published |
| `options` | Product option definitions, e.g. `[{"name":"Size","position":1,"values":["S","M","L"]}]` |
| `images` | List of image objects: `{"src","width","height","position","variantIds"}` |
| `variants` | List of variant objects (see below) |
| `url` | Direct link to the product page |
| `createdAt` / `updatedAt` | Timestamps (when available) |
| `source` | Which extraction method found the product |

#### Variant-level fields (inside `variants`)

| Field | Description |
|-------|-------------|
| `id` | Variant ID |
| `title` | Variant title |
| `sku` | Stock-keeping unit |
| `price` | Variant price (string) |
| `compareAtPrice` | Compare-at / original price (string, or `null`) |
| `available` | Whether the variant is in stock |
| `option1` / `option2` / `option3` | Structured option values (e.g. "Red", "Large") |
| `grams` | Weight in grams |
| `barcode` | Barcode / GTIN (`null` when the store doesn't publish it) |
| `requiresShipping` | Whether shipping is required |
| `taxable` | Whether the variant is taxable |
| `position` | Display position within the product |
| `featuredImage` | URL of the variant's featured image (or `null`) |

***

### Why this scraper is reliable

**Four extraction methods, tried in order** — it keeps working even when a store has
one method locked down:

1. **products.json** — Shopify's public product feed (fastest, most complete).
2. **Storefront GraphQL** — the store's own public storefront API.
3. **Collections + product pages** — reads the catalog listing and each product page.
4. **Embedded data** — reads product data embedded directly in the page HTML.

**Honest run statuses — you always know what you got:**

- ✅ **Succeeded** — the full requested catalog was scraped.
- ⚠️ **`PARTIAL: …`** status message — the store blocked or rate-limited the run partway;
  everything scraped up to that point is in the dataset, and the message says so.
  A truncated catalog is **never** silently passed off as a complete one.
- ❌ **Failed** — no products could be extracted; the run is clearly marked failed with the
  reason. It will never quietly finish "successful" with an empty dataset.

**Data you don't lose:**

- Products are **saved incrementally** as each page is fetched — a timeout or abort never
  loses what was already collected.
- Long whole-store runs are **checkpointed**: if Apify migrates or restarts the run, it
  resumes from the last completed page instead of starting over (so you don't pay twice).
- Rate limits (HTTP 429) are retried automatically with polite backoff before the scraper
  ever gives up on a method.

**Fast and cheap by design:** no headless browser — pure HTTP with a realistic browser
fingerprint. Typical speed is **hundreds of products per second** on the primary method,
which keeps compute usage (and your cost) low.

***

### Tips & limits

- Works best on standard, public Shopify storefronts. Password-protected or heavily
  customized stores may return fewer (or no) products — in that case the run tells you
  instead of pretending.
- Each internal page fetches up to **250 products** (Shopify's maximum). Pagination is
  automatic; just set `maxItems` or leave it empty for the full catalog.
- `products.json` only exposes **published, publicly visible** products — draft or hidden
  products are not (and cannot be) included.
- Be respectful: only scrape publicly available data and follow the target site's terms.

### FAQ

**Do I need a proxy?**
Usually no — Shopify's product feed is public and this scraper is polite by default.
If a specific store rate-limits you, enable Apify Proxy (datacenter) in the input.

**How do I scrape an entire store?**
Leave **Max items** empty. The actor paginates through the whole catalog automatically.

**Can it scrape prices in my currency?**
Prices are returned exactly as the store publishes them in its primary currency.

**Can it access wholesale, draft, or password-protected products?**
No. It only reads what the store makes publicly available — nothing behind a login.

**Is scraping public product data legal?**
This actor only accesses publicly available information. You are responsible for ensuring
your use complies with applicable laws and the target website's Terms of Service.

**Something didn't work — what now?**
Check the run's status message first (it always states the reason). Feel free to open an
issue on the actor's **Issues** tab with the store URL and run ID — reliability reports
are handled with priority.

***

### Disclaimer

**This is an unofficial tool. It is not affiliated with, endorsed by, sponsored by,
or in any way officially connected to Shopify Inc. or any of the stores it can be
pointed at.** "Shopify" and all related names, marks, and logos are trademarks of
their respective owners and are used here for descriptive purposes only.

This actor only accesses **publicly available** information. You are responsible for
ensuring your use complies with applicable laws, the target website's Terms of
Service, and any applicable robots and rate-limiting rules. Use it ethically and at
your own risk.

# Actor input Schema

## `storeName` (type: `string`):

A Shopify store, given as any of: myshopify handle (e.g. 'bajaao'), custom domain (e.g. 'tentree.com'), or full URL (e.g. 'https://www.tentree.com').

## `includeProducts` (type: `boolean`):

Whether to scrape products. When off, the actor exits without scraping.

## `page` (type: `integer`):

Optional starting page for the products.json strategy (advanced use). Leave at 1 to start from the beginning. Pagination continues automatically until maxItems is reached or the store is exhausted.

## `maxItems` (type: `integer`):

Maximum number of products to collect. When set, the scraper paginates automatically until this many products are collected or the store is exhausted. Leave empty (or 0) to scrape the ENTIRE store catalog across all pages.

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

Optional, off by default. Shopify's products.json is public and rarely needs a proxy. Enable Apify Proxy (datacenter is enough) only if a store rate-limits or blocks you; use residential only as a last resort.

## Actor input object example

```json
{
  "storeName": "tentree.com",
  "includeProducts": true,
  "page": 1,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All scraped products — one record per product with variants, images, options, prices, and stock status.

## `runSummary` (type: `string`):

Machine-readable summary: total products, winning extraction strategy, per-strategy attempts, and whether the result is partial.

# 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 = {
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("electrabot.info/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 = { "proxyConfiguration": { "useApifyProxy": True } }

# Run the Actor and wait for it to finish
run = client.actor("electrabot.info/shopify-product-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call electrabot.info/shopify-product-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=electrabot.info/shopify-product-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Shopify Product Scraper",
        "description": "Extract every product from any Shopify store: titles, prices, variants, stock, images, tags. Automatic whole-catalog pagination, four fallback extraction methods, honest failure reporting, no browser. Export to Excel, CSV, or JSON. Pay per result - you only pay for products delivered.",
        "version": "1.0",
        "x-build-id": "gZFlo41dsDHpvfMRT"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/electrabot.info~shopify-product-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-electrabot.info-shopify-product-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/electrabot.info~shopify-product-scraper/runs": {
            "post": {
                "operationId": "runs-sync-electrabot.info-shopify-product-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/electrabot.info~shopify-product-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-electrabot.info-shopify-product-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "storeName"
                ],
                "properties": {
                    "storeName": {
                        "title": "Store URL or handle",
                        "type": "string",
                        "description": "A Shopify store, given as any of: myshopify handle (e.g. 'bajaao'), custom domain (e.g. 'tentree.com'), or full URL (e.g. 'https://www.tentree.com')."
                    },
                    "includeProducts": {
                        "title": "Include products",
                        "type": "boolean",
                        "description": "Whether to scrape products. When off, the actor exits without scraping.",
                        "default": true
                    },
                    "page": {
                        "title": "Starting page (advanced)",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Optional starting page for the products.json strategy (advanced use). Leave at 1 to start from the beginning. Pagination continues automatically until maxItems is reached or the store is exhausted.",
                        "default": 1
                    },
                    "maxItems": {
                        "title": "Max items",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Maximum number of products to collect. When set, the scraper paginates automatically until this many products are collected or the store is exhausted. Leave empty (or 0) to scrape the ENTIRE store catalog across all pages."
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Optional, off by default. Shopify's products.json is public and rarely needs a proxy. Enable Apify Proxy (datacenter is enough) only if a store rate-limits or blocks you; use residential only as a last resort.",
                        "default": {
                            "useApifyProxy": false
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
