# Shopify Product Scraper - CSV & Excel Export (`whoareyouanas/shopify-website-product-catalogue`) Actor

Scrape public Shopify stores, collections and product URLs into CSV, Excel, JSON and ZIP. Export variants, SKUs, prices, availability and image URLs, with coverage reports and supplier CSV parts. No Shopify login or Admin API key required.

- **URL**: https://apify.com/whoareyouanas/shopify-website-product-catalogue.md
- **Developed by:** [Anas Nadeem](https://apify.com/whoareyouanas) (community)
- **Categories:** E-commerce, Developer tools
- **Stats:** 2 total users, 1 monthly users, 33.3% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 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?

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 Product Scraper** exports public Shopify product catalogs to **CSV, Excel, JSON and ZIP**. Enter store, collection or product URLs to extract product variants, SKUs, prices, tags, availability flags and gallery image URLs. Prepare supplier data, compare catalogs and review product information without a Shopify login or Admin API key.

The export includes a four-sheet Excel workbook, a CSV row for each returned variant, and a coverage report showing what was captured and which fields need review.

### What can this Shopify product scraper extract?

| Data                     | Included fields                                                                                        |
| ------------------------ | ------------------------------------------------------------------------------------------------------ |
| Products                 | Product ID, title, handle, HTML and plain-text description, vendor, product type, tags and product URL |
| Variants and SKUs        | Variant ID, SKU, barcode when exposed, selected options and source price strings                       |
| Pricing and availability | Price, compare-at price, price range and the public availability flag when returned                    |
| Product images           | Gallery URLs, image IDs, order, alt text, dimensions and variant associations when exposed             |
| Additional source fields | Shipping flag, tax flag, weight in grams, creation, update and publication timestamps                  |
| Coverage                 | Source URLs, observations, duplicate references, missing-field issues, limits and completion status    |

IDs and leading-zero SKUs remain text. Prices retain their source values. Missing data remains missing. Availability flags do not represent inventory quantities.

The Apify dataset contains one product record with nested variants and images. Its **Products, Variants and Images** views let you inspect each part, including product tags.

### How to export a Shopify catalog

1. Add one or more public Shopify store, collection or product URLs.
2. Set product limits and select your export files.
3. Start the actor and review its status and coverage report.
4. Download the CSV, Excel workbook, JSON or ZIP from the run's Storage tab. The Output tab also links to the coverage manifest.
5. Review currencies and missing fields before preparing supplier data for another system.

The restored example exports **five Silver Paw Dog products** and all four file formats. It is also the input used for Apify's daily Store test after publication. A product-limited example intentionally reports `partial` coverage while the run can finish successfully.

```json
{
  "startUrls": [{ "url": "https://silverpawdog.com/" }],
  "maxProductsPerTarget": 5,
  "maxProducts": 5,
  "exportFormats": ["csv", "xlsx", "json", "zip"]
}
```

To request a larger catalog, raise the limits. Set `maxProductsPerTarget` to `0` to remove that user cap; the global product limit and resource bounds still apply.

#### Store, collection and product URLs

| URL pattern                                        | Requested scope                                 |
| -------------------------------------------------- | ----------------------------------------------- |
| `https://store.example/`                           | The public store catalog                        |
| `https://store.example/collections/rainwear`       | That collection                                 |
| `https://store.example/products/rain-jacket`       | That product and its returned variants          |
| `https://store.example/en-ca/collections/rainwear` | That collection with the locale prefix retained |

Bare domains are accepted. Tracking parameters are ignored, and a product's variant parameter does not reduce the exported variant list. Unsupported routes and collection filters are rejected so the requested scope stays clear.

Overlapping store, collection and product inputs merge source references for the same product in the same observed store and locale. Bare-domain and `www` aliases also merge when supported by the store's canonical-domain metadata.

### Shopify CSV, Excel and JSON output

| File or output                 | What you receive                                                                      |
| ------------------------------ | ------------------------------------------------------------------------------------- |
| Default dataset                | Product records with nested variants, tags, gallery details and source references     |
| `catalog.csv`                  | One row per returned variant, with product fields, SKU, prices, tags and gallery URLs |
| `catalog.xlsx`                 | **Products, Variants, Images and Coverage** sheets; literal values stored as text     |
| `images.csv`                   | Product-gallery associations and exposed image metadata                               |
| `observed-catalog.json`        | Full normalized product records                                                       |
| `issues.csv`                   | Source, product, variant and export issues                                            |
| `manifest.json`                | Capture status, counts, coverage and file links with integrity hashes                 |
| `workbench-part-001.csv`, etc. | Supplier CSV parts within 500 products, 2,500 variants and 10 MB per file             |
| `workbench-parts.json`         | Supplier-part counts, sizes, hashes and download keys                                 |
| `catalog-002.xlsx`, etc.       | Additional workbook parts when required                                               |
| `catalog.zip`                  | The preparation files and an embedded manifest                                        |

Supplier parts preserve whole product groups. A single product exceeding a part's bounds remains in the full export and receives an explicit issue.

ZIP includes CSV, XLSX and JSON. XLSX also retains JSON so full text remains available when a value exceeds Excel's cell limit. Image exports contain URLs and metadata; image binaries are not downloaded.

#### Example product JSON

This shortened example uses illustrative values. Actual records include further metadata and coverage fields.

```json
{
  "productId": "9007199254740993",
  "title": "Dog Rain Jacket",
  "handle": "dog-rain-jacket",
  "tags": ["Rainwear", "Dogs"],
  "currency": null,
  "currencyStatus": "unknown",
  "variantCount": 1,
  "variants": [
    {
      "variantId": "9007199254740994",
      "sku": "00042",
      "price": "29.90",
      "compareAtPrice": "39.90",
      "available": true,
      "selectedOptions": [{ "name": "Size", "value": "M" }]
    }
  ],
  "images": [
    {
      "url": "https://cdn.example/rain-jacket.jpg",
      "position": "1",
      "variantIds": []
    }
  ]
}
```

### Prepare supplier catalog data

Use the variant CSV to map product groups, SKUs, options, prices and tags in your supplier preparation workflow. The bounded supplier parts support the Catalog Prep workbench's upload limits.

The workbook keeps product, variant, image and coverage information in separate sheets for review. Confirm the source price currency, resolve missing fields and duplicate SKUs, then review the product groups before creating destination drafts.

The exported supplier CSV is a source-data format. Creating a native Shopify import file requires a destination mapping and review. This actor does not write to Shopify.

### Input settings

The small restored example uses five products. API calls that provide URLs but omit limits use the API defaults below.

| Input                  | API default | Meaning                                                                     |
| ---------------------- | ----------- | --------------------------------------------------------------------------- |
| `startUrls`            | Required    | 1–100 store, collection or product URLs; restored example: Silver Paw Dog         |
| `maxProductsPerTarget` | `1000`      | Per-URL product limit; `0` removes this user cap; restored example: `5`     |
| `maxProducts`          | `10000`     | Global unique-product limit, up to 25,000; restored example: `5`            |
| `exportFormats`        | All four    | `csv`, `xlsx`, `json`, `zip`; `[]` retains the dataset, manifest and issues |
| `currencyOverrides`    | `[]`        | Explicit currency assertions for an observed store and locale               |
| `saveSourceResponses`  | `false`     | Retain exact feed text and hashes for auditing; adds storage usage          |
| `maxConcurrency`       | `3`         | Parallel store contexts, from 1–10                                          |
| `requestIntervalMs`    | `1000`      | Minimum request interval per store context, from 500–60,000 ms              |

#### Confirming the price currency

A public feed may omit currency. Without an assertion, `currency` stays null; a page or metadata currency hint remains separate.

If you have confirmed the source currency, provide an override:

```json
{
  "currencyOverrides": [
    {
      "storeUrl": "https://supplier.example",
      "localePrefix": "/en-ca",
      "currency": "CAD"
    }
  ]
}
```

Overrides label the currency as `operator_asserted`. They do not convert prices or automatically verify the source currency.

### Shopify scraper API and scheduled exports

Run the actor from Apify Console, through the API, or from an Apify task. The API requires your Apify token; no Shopify Admin API credentials are needed.

```sh
curl --request POST \
  "https://api.apify.com/v2/acts/whoareyouanas~shopify-website-product-catalogue/runs" \
  --header "Authorization: Bearer $APIFY_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "startUrls": [{"url": "https://silverpawdog.com/"}],
    "maxProductsPerTarget": 5,
    "maxProducts": 5,
    "exportFormats": ["csv", "xlsx", "json", "zip"]
  }'
```

The response supplies the run and storage IDs. Use the default dataset for product records and the key-value store for prepared files. Private output links require Apify authentication.

To export a catalog daily, save your input as an Apify task and attach a schedule. Each scheduled run creates a new capture. This actor produces catalog snapshots; comparing changes across runs requires your own comparison workflow.

### Coverage and troubleshooting

| Status         | Meaning                                                                                                |
| -------------- | ------------------------------------------------------------------------------------------------------ |
| `complete`     | Requested supported public sources were exhausted without a known coverage issue                       |
| `partial`      | A cap, count discrepancy, source failure, uncertain variant coverage or export issue limits the result |
| `empty_source` | A supported source returned no products                                                                |
| `failed`       | No requested target returned usable product data                                                       |

Read target-level status and stop reasons in the manifest. A successful run can have `partial` coverage, including the five-product example.

Cloud tests on 26 October 2026 captured **397 Allbirds products with 4,615 variants** and **139 Silver Paw products with 469 variants**. Silver Paw's root feed returned 139 products while its metadata and “all” collection reported 135; the export retained all root-feed products and disclosed the count discrepancy. Counts can change after a capture.

Limits include 25,000 unique products per run, 100 pages per target, 100,000 returned variants, 10 MB per decompressed response, bounded staging and export sizes, and a 15-minute capture deadline. Generated standard files have a 100 MB aggregate budget; ZIP has a separate 100 MB bound. Reaching a bound preserves completed data and reports the limitation.

Sources returning 250 or more variants for a product, or advertising more variants than they return, receive a coverage warning. Protected, custom or headless storefronts may be unsupported. Proxy routing is currently unavailable.

### Pricing and result counting

Check the actor's **Pricing** tab for current charges. The published tariff charges per product in the default dataset and includes a platform startup fee. Variants and standard export files have no separate product fee.

The result unit is one unique product per observed store and locale context. Its returned variants, gallery URLs and standard export files belong to that product. Duplicate references within a capture do not create additional product records. New runs create new observations.

### Frequently asked questions

#### Can I export Shopify products without an Admin API key?

Yes, when a supported public storefront feed exposes the data. The actor does not require a Shopify login or merchant Admin API access. Protected or incompatible storefronts can return an unsupported or blocked result.

#### Can I scrape Shopify variants, SKUs and tags?

Yes. Variants are nested under each product in JSON and expanded into rows in the variant CSV and Excel sheet. Product tags appear in JSON, CSV, the product workbook sheet and the Apify Products view. Empty or unexposed fields remain empty.

#### Does the Excel export preserve leading zeros and long IDs?

Yes. The prepared XLSX writes literal values as text, preserving long product IDs and leading-zero SKUs. Use the typed workbook for spreadsheet inspection. Exact CSV text can be interpreted differently by spreadsheet software.

#### Does the scraper return inventory quantities?

It preserves public availability flags when returned. Private stock quantities are not collected or inferred.

#### Is this a ready-to-import Shopify CSV?

The export is designed for catalog extraction and supplier data preparation. Native Shopify imports need destination-specific mapping and review. The actor does not import, publish or modify products in Shopify.

#### Why does a successful run say partial?

A product cap deliberately stops capture early. Other causes include conflicting source counts, failed targets, suspected source truncation and export limits. The manifest explains the reason and lists the records that were delivered.

#### Does the scraper download product images?

It exports returned gallery image URLs and metadata. It does not download image binaries or verify that every URL is reachable.

#### How do I report a problem?

Open an issue on this actor's Apify page with the run ID, requested scope and the manifest's stop reason. Include the source URL and missing field when relevant. Keep API tokens and other credentials private.

# Actor input Schema

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

Public HTTPS Shopify roots, collections or product URLs. Locale prefixes are preserved. Unsupported filters are rejected rather than widened to a full-store capture.

## `maxProductsPerTarget` (type: `integer`):

0 removes this user cap; global, page, byte, variant and time bounds still apply. A capped result is marked partial.

## `maxProducts` (type: `integer`):

Global product limit. Overlapping scopes in the same observed store/locale context count once. Apify's maximum charge per run also applies.

## `exportFormats` (type: `array`):

Choose csv, xlsx, json and/or zip. ZIP includes the standard formats. XLSX includes normalized JSON for full text exceeding Excel cell limits. The product dataset and coverage manifest are always available.

## `currencyOverrides` (type: `array`):

Optional operator assertions: \[{"storeUrl":"https://supplier.example","localePrefix":"","currency":"CAD"}]. Does not convert prices or verify currency. Without an assertion, feed currency stays unknown.

## `saveSourceResponses` (type: `boolean`):

Save the exact accepted feed response text in the run's key-value store. Manifest observations link each response and its hash, allowing export reconciliation even when a live catalogue changes. Adds storage usage; disabled by default.

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

Different store contexts run concurrently; targets within a context are processed sequentially.

## `requestIntervalMs` (type: `integer`):

Minimum pause between requests to a store context. Persistent throttling is reported explicitly.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://silverpawdog.com/"
    }
  ],
  "maxProductsPerTarget": 5,
  "maxProducts": 5,
  "exportFormats": [
    "csv",
    "xlsx",
    "json",
    "zip"
  ],
  "currencyOverrides": [],
  "saveSourceResponses": false,
  "maxConcurrency": 3,
  "requestIntervalMs": 1000
}
```

# Actor output Schema

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

No description

## `manifest` (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": [
        {
            "url": "https://silverpawdog.com/"
        }
    ],
    "maxProductsPerTarget": 5,
    "maxProducts": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("whoareyouanas/shopify-website-product-catalogue").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": [{ "url": "https://silverpawdog.com/" }],
    "maxProductsPerTarget": 5,
    "maxProducts": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("whoareyouanas/shopify-website-product-catalogue").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": [
    {
      "url": "https://silverpawdog.com/"
    }
  ],
  "maxProductsPerTarget": 5,
  "maxProducts": 5
}' |
apify call whoareyouanas/shopify-website-product-catalogue --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,whoareyouanas/shopify-website-product-catalogue"
        }
    }
}
```

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/YIGC1aIMvgvl2f3Zj/builds/e0ftfAFl8kPMctqGK/openapi.json
