# Shopify Products Scraper — Prices, Variants & SKUs (`funny_ground/shopify-products-scraper`) Actor

Export public Shopify catalog data from store, collection or product URLs: products, variant prices, SKUs, images and availability. Product-event and memory-based startup fees apply; platform usage is billed separately.

- **URL**: https://apify.com/funny_ground/shopify-products-scraper.md
- **Developed by:** [Coor Yu](https://apify.com/funny_ground) (community)
- **Categories:** E-commerce, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 shopify products

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 Products Scraper — Prices, Variants & SKUs

Shopify Products Scraper exports public Shopify products, variant prices, SKUs, compare-at prices, availability, images, options and tags. Use a **store, collection or product URL** for catalog and price research.

**One saved product = one product event. All variants exposed in that product's public JSON are included.** There is no per-variant or per-store surcharge. No Shopify account or Admin API key is required; running through the Apify API requires your Apify token.

### Quick start

1. Replace the Allbirds demo with your target Shopify URLs.
2. Keep **100 products per URL**, or adjust the limits below.
3. Click Start and export the Products dataset as JSON, CSV or Excel.

```json
{
  "storeUrls": ["https://www.allbirds.com", "https://kith.com"],
  "maxProductsPerStore": 100
}
```

`{}` selects the **paid Allbirds demo**, requesting up to 100 products. At the configured 256 MB memory, 100 saved products cost **$0.085 in event fees, plus actual Apify platform usage**. The two-URL example can save up to 200 products, subject to other limits. Example storefront accessibility is not guaranteed.

Bare domains such as `kith.com` are accepted. Tracking parameters, fragments and repeated URL scopes are removed automatically.

#### Store, collection and single-product exports

- **Store URL:** paginate the store's public `/products.json` catalog.
- **Collection URL:** paginate only that collection's public product feed; no collection rows are saved or charged.
- **Product URL:** request that product's public JSON, including exposed variants—not only the variant selected in a query string.

```json
{
  "storeUrls": [
    "https://your-store.com/collections/sale",
    "https://your-store.com/products/a-product-handle"
  ],
  "maxProductsPerStore": 50,
  "includeDescription": true
}
```

Replace these illustrative URLs with accessible storefronts. Common locale prefixes such as `/en-us/` are retained. No Shopify Admin API or private inventory is accessed.

### Input fields

| Field | Default | Purpose |
|---|---|---|
| `storeUrls` | Allbirds demo | 1–20 public store, collection or product URLs |
| `maxProductsPerStore` | 100 | Matching products saved from **each URL scope**, 1–5,000 |
| `maxProducts` | 1,000 | Global saved-product cap across all scopes, 1–10,000 |
| `onlyAvailable` | false | Require at least one explicitly available variant |
| `includeDescription` | false | Include plain-text descriptions, limited to 10,000 characters |
| `minPrice`, `maxPrice` | unset | Inclusive variant-price filters; nonnegative numbers, with minimum no greater than maximum |

When availability and price filters are combined, **the same variant must satisfy all conditions**. Filters select products; returned products still include their other exposed variants. Prices use each storefront's currency without conversion. Restrictive filters can cause more pages to be fetched than products saved; platform usage still applies.

### Output and billing unit

Each dataset row is one product, with:

- `id`, `handle`, `title`, `vendor`, `productType`, product URL and store/domain details
- `currency` when public shop metadata exposes it; numeric `minPrice` and `maxPrice` calculated from exposed variant prices
- `available`, `onSale` and `variantCount`, derived from returned variants
- `variants`: IDs, titles, SKUs, barcode when exposed, numeric prices, compare-at prices, option values, weight, shipping and availability flags
- Product image URLs, tags and option definitions
- Source `createdAt`, `updatedAt` and `publishedAt` strings when exposed; `sourceUrl` and collection-time `scrapedAt`
- Optional plain-text `description`

Missing nullable values stay `null`. Availability is a storefront flag, **not an exact inventory count**. `onSale` indicates a compare-at price above the variant price, not a verified promotion. No sales, revenue, orders, customer data or supplier costs are inferred.

JSON retains nested variants; CSV/Excel may stringify arrays. For one row per SKU, expand `variants` downstream. Billing remains per product.

### Current pricing: product events + platform usage

Current configured prices are in USD; see the [Pricing tab](https://apify.com/funny_ground/shopify-products-scraper/pricing) for authoritative effective pricing.

| Charge | Current rate |
|---|---|
| `apify-default-dataset-item` | **$0.0008 per saved product — $0.80 per 1,000** |
| `apify-actor-start` | **$0.005 per GB of allocated memory, minimum one startup event per run** |
| Exposed variants, images and optional descriptions | Included in the product event |
| Apify platform usage | **Billed separately to the running user** at their Apify plan rates |

The current Actor memory is fixed at **256 MB**, so its minimum one-event startup charge is **$0.005**. Startup is memory-based, not fixed at every memory setting.

At that configured memory:

| Saved products | Event fees, excluding platform usage |
|---|---:|
| 1 | $0.0058 |
| 100 | $0.085 |
| 1,000 | $0.805 |

Total cost = startup events + saved-product events + actual platform usage. Compute, transfer and storage can cost money on empty/failed runs; retaining or reading datasets can also incur charges. No paid upstream Actors, data services, browsers, residential proxies or automatic paid fallbacks are called.

The startup charge can apply even if a store is blocked, empty, invalid or filtered to zero matches. Failed fetches, malformed/filtered products, skipped duplicates and the key-value run summary do **not** produce product events. Deduplication uses store domain + product ID within the run, including overlapping URL scopes; different store domains are separate records.

Apify's **Maximum charge per run** caps event charges; the configured minimum cap is **$0.0058**. Remaining product-event allowance is checked before requests and writes. The cap excludes platform usage and cannot guarantee a complete export.

### Reliability and limits

- Public product JSON feeds only. Password protection, login pages, bot challenges, missing feeds and HTTP errors are not bypassed.
- Sequential scope/page processing, with one retry for HTTP 5xx errors; no repeated rate-limit or permanent-error retries.
- Two-minute collection deadline, 100 HTTP requests including metadata/redirects/retries, 15-second request deadline and 8 MiB per response.
- Public HTTPS storefronts only. Internal/local targets, URL credentials and unsafe redirects are rejected.
- Repeated pages are detected and stopped. Budget, global-product, request and time limits can leave later scopes unvisited.

The `OUTPUT` key-value record provides per-scope counts, skipped duplicates, filter counts, errors and stop reasons. Mixed failures retain products with a partial summary; if every feed fails, the run fails. Valid empty catalogs or zero filter matches can succeed without rows; startup and platform charges still apply.

Public feeds may change, expose fewer products or variants than requested, or report delayed availability. Split large or heavily filtered crawls into smaller runs. Use only data you are entitled to access and follow applicable site terms and laws.

### FAQ

**Can I export an entire Shopify store?**\
You can request its public catalog, but completeness depends on exposed feeds, product limits, event budget and safety deadlines. This is not an Admin API export.

**Are all SKUs and stock quantities available?**\
Only SKUs and availability flags exposed in public product JSON are returned. Private stock quantities and missing barcodes are not recovered.

### Related Actors

- [WooCommerce Store Products Scraper](https://apify.com/funny_ground/woocommerce-store-products-scraper) — for public WooCommerce catalogs instead of Shopify feeds.
- [Website Contact & Social Scraper](https://apify.com/funny_ground/website-contact-social-scraper) — for publicly listed website contacts and social links, separate from catalog data.

# Actor input Schema

## `storeUrls` (type: `array`):

Paste store homepages, collection URLs or individual product URLs. Bare domains are accepted. URLs are normalized and repeated products are billed only once per store in a run. Replace the Allbirds demo with your own targets.

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

Limit matching products from each URL scope. All variants are included within each product. Store defaults: 100 products, $0.085 in event fees plus actual platform usage. Up to 5,000, subject to the global, time and request caps.

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

Global cap across all URLs, after deduplication and filters. The Actor also respects your event-charge budget and a two-minute collection deadline. Platform usage is charged separately.

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

Return a product when at least one variant is explicitly available. When price filters are set, the same variant must also match those filters. Availability is not an exact inventory count.

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

Add available product descriptions, converted to plain text and limited to 10,000 characters. No extra product fee.

## `minPrice` (type: `number`):

At least one variant must meet the price filters. Values use each storefront’s currency, not a converted currency. Leave blank for no minimum.

## `maxPrice` (type: `number`):

At least one variant must meet the price filters. Must not be below the minimum price. Leave blank for no maximum.

## Actor input object example

```json
{
  "storeUrls": [
    "https://www.allbirds.com"
  ],
  "maxProductsPerStore": 100,
  "maxProducts": 1000,
  "onlyAvailable": false,
  "includeDescription": false
}
```

# Actor output Schema

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

Unique products with available variants, prices, SKUs, images and stock-availability flags.

## `summary` (type: `string`):

Per-URL counts, errors, limits and warnings. Summaries are not billed as products.

# 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 = {
    "storeUrls": [
        "https://www.allbirds.com"
    ],
    "maxProductsPerStore": 100,
    "maxProducts": 1000,
    "onlyAvailable": false,
    "includeDescription": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("funny_ground/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 = {
    "storeUrls": ["https://www.allbirds.com"],
    "maxProductsPerStore": 100,
    "maxProducts": 1000,
    "onlyAvailable": False,
    "includeDescription": False,
}

# Run the Actor and wait for it to finish
run = client.actor("funny_ground/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 '{
  "storeUrls": [
    "https://www.allbirds.com"
  ],
  "maxProductsPerStore": 100,
  "maxProducts": 1000,
  "onlyAvailable": false,
  "includeDescription": false
}' |
apify call funny_ground/shopify-products-scraper --silent --output-dataset

```

## MCP server setup

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