# Shopify Scraper Pro (`crawlerbros/shopify-scraper-pro`) Actor

Scrape any Shopify store(s) at scale: products, collections, search, on-sale tracking, multi-store batches. Filters: price/vendor/type/tags/title/sale/availability/date. Multi-endpoint fallback. HTTP-only, no auth, no proxy.

- **URL**: https://apify.com/crawlerbros/shopify-scraper-pro.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** E-commerce, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 13 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $1.00 / 1,000 results

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

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 Scraper Pro

The most capable Shopify catalog scraper on Apify Store. **Multi-store batches**, **collection-scoped scraping**, **in-store search**, **sale tracking with discount %**, **endpoint fallback chain**, **image quality control**, **13 filter dimensions**, and **automatic proxy fallback**. Pulls structured product data from any Shopify-powered store via public APIs — no login, no cookies, no proxy required for most stores.

### What's "Pro" about it

| Capability | Basic Shopify scrapers | **Shopify Pro** |
|---|---|---|
| Stores per run | 1 | **N** (multi-store batch) |
| Collection-scoped | ❌ | ✅ `collectionHandles` |
| In-store search | ❌ | ✅ `searchQuery` via `/search/suggest.json` |
| Endpoint fallback | `/products.json` only | `/products.json` → `/collections/all/products.json` → collection-specific |
| Sort options | ❌ | 8 (best-selling, price asc/desc, title, created…) |
| Image quality | original only | 7 sizes (small/medium/large/grande/1024/2048/master) |
| Filters | 0-2 | **13 dimensions** |
| Sale tracking | ❌ or basic | `onSale`, `comparePrice`, `discountPercent` (derived) |
| Date filters | ❌ | `createdSince`, `updatedSince` |
| SKU search | ❌ | `skuContains` |
| Auto proxy fallback | ❌ | ✅ retries with Apify proxy on first failure |
| Output fields | ~17 | **27** (incl. `discountPercent`, `maxPrice`, `availableVariantCount`, `storeCollections`) |

### Modes

The actor runs in one of three modes per store:

1. **Full catalog** (default) — walks `/products.json` (and falls back to `/collections/all/products.json`) until the catalog is exhausted
2. **Collection** (`collectionHandles=[...]`) — fetches `/collections/<handle>/products.json` with the chosen `sortBy`
3. **Search** (`searchQuery=...`) — uses `/search/suggest.json` to find the most relevant matches

### Output per product

- `productId`, `handle`, `productUrl`, `storeUrl`
- `title`, `vendor`, `productType`
- `description` (HTML stripped, capped at 5000 chars)
- `tags[]`
- `price` (lowest variant), `maxPrice` (when range), `comparePrice`, `onSale`, **`discountPercent`** (derived)
- `currency` — when discoverable
- `variantCount`, `availableVariantCount`, `available`
- `skus[]` (up to 20)
- `variants[]` (up to 30 — `id`, `title`, `sku`, `price`, `comparePrice`, `available`, `option1/2/3`)
- `imageUrl` (cover, transformed to chosen `imageQuality`), `images[]` (up to 15, all transformed)
- `options[]` (size/color etc — `name`, `values[]`)
- `createdAt`, `updatedAt`, `publishedAt`
- `collections[]` — when `enrichWithCollections=true` and product matches store collections
- `storeCollections[]` — flat list of all collections in the store
- `scrapedFromCollection` — when scraped via collection mode
- `recordType: "product"`, `scrapedAt`

Empty fields are omitted from the output (no nulls).

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `storeUrls` | array | `["allbirds.com","kith.com"]` | Shopify store domains. Accepts full URLs, bare domains, or `*.myshopify.com` handles |
| `collectionHandles` | array | `[]` | When set, fetch `/collections/<handle>/products.json` instead of full catalog. Applies to ALL stores |
| `searchQuery` | string | – | When set, runs in-store search via `/search/suggest.json` |
| `sortBy` | enum | `best-selling` | Collection mode sort: `best-selling`, `manual`, `price-ascending`, `price-descending`, `title-ascending`, `title-descending`, `created-ascending`, `created-descending` |
| `imageQuality` | enum | `master` | Image URL quality: `small`/`medium`/`large`/`grande`/`1024x1024`/`2048x2048`/`master` |
| `enrichWithCollections` | bool | `false` | Fetch each store's `/collections.json` to enrich products with collection metadata |
| `maxItemsPerStore` | int | `250` | Hard cap per store (1-5000) |
| `maxItems` | int | `1000` | Global hard cap (1-50000) |
| `includeUnavailable` | bool | `false` | Drop products whose variants are all out-of-stock |
| `minPrice` | number | – | Drop products below this price |
| `maxPrice` | number | – | Drop products above this price |
| `vendorContains` | string | – | Only emit products whose vendor contains this substring |
| `productTypeContains` | string | – | Only emit products whose `product_type` contains this substring |
| `tagAnyOf` | array | `[]` | Only emit products whose tags contain at least one of these |
| `tagNoneOf` | array | `[]` | Drop products whose tags contain any of these |
| `titleContains` | string | – | Only emit products whose title contains this substring |
| `onSaleOnly` | bool | `false` | Only emit products with `compare_at_price > price` |
| `minDiscountPercent` | int | – | Only emit products discounted by at least this % |
| `createdSince` | string | – | Drop products created before this ISO date (`YYYY-MM-DD`) |
| `updatedSince` | string | – | Drop products updated before this ISO date |
| `skuContains` | string | – | Only emit products with at least one variant whose SKU contains this substring |
| `useApifyProxy` | bool | `false` | Force proxy from start. Auto-fallback to proxy happens regardless |
| `requestDelaySecs` | int | `1` | Pause between page fetches (0–10s) |

#### Example: full catalog from one store

```json
{
  "storeUrls": ["allbirds.com"],
  "maxItemsPerStore": 500,
  "imageQuality": "large"
}
````

#### Example: men's sale collection sorted by price

```json
{
  "storeUrls": ["allbirds.com"],
  "collectionHandles": ["mens-sale"],
  "sortBy": "price-ascending",
  "onSaleOnly": true,
  "minDiscountPercent": 30,
  "maxItems": 50
}
```

#### Example: in-store search across multiple stores

```json
{
  "storeUrls": ["allbirds.com", "rothys.com"],
  "searchQuery": "wool runner",
  "maxItems": 30
}
```

#### Example: track new arrivals from competitors

```json
{
  "storeUrls": ["kith.com", "endclothing.com", "ssense.com"],
  "createdSince": "2026-04-01",
  "tagAnyOf": ["new-arrivals", "new"],
  "minPrice": 100,
  "imageQuality": "1024x1024"
}
```

#### Example: sale tracker with rich output

```json
{
  "storeUrls": ["allbirds.com", "everlane.com", "rothys.com"],
  "onSaleOnly": true,
  "minDiscountPercent": 40,
  "enrichWithCollections": true,
  "maxItems": 200
}
```

### Use cases

- **Competitor monitoring** — pull a competitor's full catalog weekly, track new launches with `createdSince`
- **Sale tracking** — daily run with `onSaleOnly: true` + `minDiscountPercent: 30` to alert on deep discounts
- **Multi-brand aggregator** — feed a price-comparison site with N store catalogs in one run
- **Inventory snapshot** — combine `availableVariantCount` and `updatedSince` to track stock churn
- **Brand intelligence** — `vendorContains` to extract products from a specific brand carried by a multi-brand store
- **Product-feed migration** — export a Shopify catalog as clean JSON for import elsewhere
- **In-store search analytics** — `searchQuery` mode to see what each store surfaces for a keyword

### FAQ

**Does it require a login or cookies?**  No. The actor uses public Shopify storefront endpoints.

**Is a proxy needed?**  Usually no — most Shopify stores serve datacenter IPs. The actor automatically retries with Apify proxy on the first failure, so stores that block cloud IPs still work transparently.

**Which stores does it work on?**  Any store using Shopify with the public products feed enabled — the vast majority of the 5M+ live Shopify stores. Some stores explicitly disable `/products.json`; for those, the `/collections/all/products.json` fallback often still works.

**How is `discountPercent` calculated?**  When a product's lowest variant price (`price`) is below the `compare_at_price`, we compute `100 * (1 - price/comparePrice)` and round down. Only emitted when the value is between 1 and 99.

**Why is `currency` not always included?**  Shopify's `/products.json` doesn't include a currency field at the product level. We add it when discoverable elsewhere; otherwise it's omitted (no nulls).

**Can I scrape a specific collection?**  Yes — set `collectionHandles: ["sale", "new-arrivals"]`. The actor will hit `/collections/<handle>/products.json` with your chosen `sortBy`.

**What does `imageQuality` actually do?**  Shopify's CDN serves multiple sizes via URL suffixes. e.g. `abc.jpg` → `abc_small.jpg` → `abc_1024x1024.jpg`. The actor rewrites every image URL to the chosen size. `master` returns the original.

**How does `searchQuery` differ from `titleContains`?**  `searchQuery` calls Shopify's own search backend (returns ranked, server-side relevance). `titleContains` is a client-side substring filter applied AFTER fetching the catalog. Use `searchQuery` for relevance, `titleContains` for catalog scans.

**How fresh is the data?**  Real-time. Endpoints serve the live catalog snapshot.

**What's the difference between `available` and `availableVariantCount`?**  `available` is `true` when at least one variant is in stock. `availableVariantCount` is the integer count of in-stock variants. Both are reliable sale indicators.

# Actor input Schema

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

Shopify store domains. Accepts full URLs (`https://www.allbirds.com`), bare domains (`allbirds.com`), or `*.myshopify.com` handles. Each store is fetched independently.

## `collectionHandles` (type: `array`):

Restrict scraping to specific collection handles (e.g. `mens`, `sale`, `new-arrivals`). When set, fetches `<store>/collections/<handle>/products.json` instead of the full catalog. Applies to ALL `storeUrls`.

## `searchQuery` (type: `string`):

When set, runs Shopify's in-store search via `<store>/search/suggest.json?q=<query>` instead of catalog walk. Returns the most relevant matches per store.

## `sortBy` (type: `string`):

Shopify's collection sort. Only applied when `collectionHandles` is set.

## `maxItemsPerStore` (type: `integer`):

Hard cap on products fetched per store (1-5000).

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

Global hard cap across all stores (1-50000).

## `imageQuality` (type: `string`):

Shopify CDN serves multiple image sizes. `master` returns the original; smaller sizes are bandwidth-friendly.

## `enrichWithCollections` (type: `boolean`):

Fetch each store's `/collections.json` and add a `collections[]` field to each product (matched by handle when possible). Adds 1 extra HTTP request per store.

## `includeUnavailable` (type: `boolean`):

When false (default), drop products whose variants are all out-of-stock.

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

Drop products whose lowest variant price is below this threshold.

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

Drop products whose lowest variant price is above this threshold.

## `vendorContains` (type: `string`):

Only emit products whose vendor name contains this substring (case-insensitive).

## `productTypeContains` (type: `string`):

Only emit products whose `product_type` (Shopify taxonomy) contains this substring.

## `tagAnyOf` (type: `array`):

Only emit products whose `tags` list contains at least one of these (case-insensitive substring match).

## `tagNoneOf` (type: `array`):

Drop products whose `tags` contains any of these substrings.

## `titleContains` (type: `string`):

Only emit products whose title contains this substring (case-insensitive).

## `onSaleOnly` (type: `boolean`):

Only emit products with at least one variant where `compare_at_price` > `price` (i.e. discounted).

## `minDiscountPercent` (type: `integer`):

Only emit products whose discount (`comparePrice` vs `price`) is at least this percentage. e.g. `30` = at least 30% off.

## `createdSince` (type: `string`):

Drop products created (`created_at`) before this date. Empty = no lower bound.

## `updatedSince` (type: `string`):

Drop products updated (`updated_at`) before this date. Empty = no lower bound.

## `skuContains` (type: `string`):

Only emit products with at least one variant whose SKU contains this substring (case-insensitive).

## `useApifyProxy` (type: `boolean`):

Route requests through Apify proxy. Most Shopify stores work without proxy from datacenter IPs. The actor automatically falls back to Apify proxy on the first failure regardless of this setting.

## `requestDelaySecs` (type: `integer`):

Pause between successive page fetches per store. Lower = faster, higher = more polite.

## Actor input object example

```json
{
  "storeUrls": [
    "allbirds.com",
    "kith.com"
  ],
  "collectionHandles": [],
  "sortBy": "best-selling",
  "maxItemsPerStore": 250,
  "maxItems": 1000,
  "imageQuality": "master",
  "enrichWithCollections": false,
  "includeUnavailable": false,
  "tagAnyOf": [],
  "tagNoneOf": [],
  "onSaleOnly": false,
  "useApifyProxy": false,
  "requestDelaySecs": 1
}
```

# 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": [
        "allbirds.com",
        "kith.com"
    ],
    "collectionHandles": [],
    "sortBy": "best-selling",
    "maxItemsPerStore": 250,
    "maxItems": 1000,
    "imageQuality": "master",
    "enrichWithCollections": false,
    "includeUnavailable": false,
    "tagAnyOf": [],
    "tagNoneOf": [],
    "onSaleOnly": false,
    "useApifyProxy": false,
    "requestDelaySecs": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/shopify-scraper-pro").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": [
        "allbirds.com",
        "kith.com",
    ],
    "collectionHandles": [],
    "sortBy": "best-selling",
    "maxItemsPerStore": 250,
    "maxItems": 1000,
    "imageQuality": "master",
    "enrichWithCollections": False,
    "includeUnavailable": False,
    "tagAnyOf": [],
    "tagNoneOf": [],
    "onSaleOnly": False,
    "useApifyProxy": False,
    "requestDelaySecs": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/shopify-scraper-pro").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 '{
  "storeUrls": [
    "allbirds.com",
    "kith.com"
  ],
  "collectionHandles": [],
  "sortBy": "best-selling",
  "maxItemsPerStore": 250,
  "maxItems": 1000,
  "imageQuality": "master",
  "enrichWithCollections": false,
  "includeUnavailable": false,
  "tagAnyOf": [],
  "tagNoneOf": [],
  "onSaleOnly": false,
  "useApifyProxy": false,
  "requestDelaySecs": 1
}' |
apify call crawlerbros/shopify-scraper-pro --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Shopify Scraper Pro",
        "description": "Scrape any Shopify store(s) at scale: products, collections, search, on-sale tracking, multi-store batches. Filters: price/vendor/type/tags/title/sale/availability/date. Multi-endpoint fallback. HTTP-only, no auth, no proxy.",
        "version": "1.0",
        "x-build-id": "QXg3cKsGalVNGFEzE"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/crawlerbros~shopify-scraper-pro/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-crawlerbros-shopify-scraper-pro",
                "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/crawlerbros~shopify-scraper-pro/runs": {
            "post": {
                "operationId": "runs-sync-crawlerbros-shopify-scraper-pro",
                "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/crawlerbros~shopify-scraper-pro/run-sync": {
            "post": {
                "operationId": "run-sync-crawlerbros-shopify-scraper-pro",
                "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": [
                    "storeUrls"
                ],
                "properties": {
                    "storeUrls": {
                        "title": "Shopify store URLs",
                        "type": "array",
                        "description": "Shopify store domains. Accepts full URLs (`https://www.allbirds.com`), bare domains (`allbirds.com`), or `*.myshopify.com` handles. Each store is fetched independently.",
                        "default": [
                            "allbirds.com",
                            "kith.com"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "collectionHandles": {
                        "title": "Collection handles (optional)",
                        "type": "array",
                        "description": "Restrict scraping to specific collection handles (e.g. `mens`, `sale`, `new-arrivals`). When set, fetches `<store>/collections/<handle>/products.json` instead of the full catalog. Applies to ALL `storeUrls`.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "searchQuery": {
                        "title": "In-store search query (optional)",
                        "type": "string",
                        "description": "When set, runs Shopify's in-store search via `<store>/search/suggest.json?q=<query>` instead of catalog walk. Returns the most relevant matches per store."
                    },
                    "sortBy": {
                        "title": "Sort by (collection mode only)",
                        "enum": [
                            "best-selling",
                            "manual",
                            "price-ascending",
                            "price-descending",
                            "title-ascending",
                            "title-descending",
                            "created-ascending",
                            "created-descending"
                        ],
                        "type": "string",
                        "description": "Shopify's collection sort. Only applied when `collectionHandles` is set.",
                        "default": "best-selling"
                    },
                    "maxItemsPerStore": {
                        "title": "Max items per store",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Hard cap on products fetched per store (1-5000).",
                        "default": 250
                    },
                    "maxItems": {
                        "title": "Max items total",
                        "minimum": 1,
                        "maximum": 50000,
                        "type": "integer",
                        "description": "Global hard cap across all stores (1-50000).",
                        "default": 1000
                    },
                    "imageQuality": {
                        "title": "Image URL quality",
                        "enum": [
                            "small",
                            "medium",
                            "large",
                            "grande",
                            "1024x1024",
                            "2048x2048",
                            "master"
                        ],
                        "type": "string",
                        "description": "Shopify CDN serves multiple image sizes. `master` returns the original; smaller sizes are bandwidth-friendly.",
                        "default": "master"
                    },
                    "enrichWithCollections": {
                        "title": "Enrich with collections list",
                        "type": "boolean",
                        "description": "Fetch each store's `/collections.json` and add a `collections[]` field to each product (matched by handle when possible). Adds 1 extra HTTP request per store.",
                        "default": false
                    },
                    "includeUnavailable": {
                        "title": "Include unavailable products",
                        "type": "boolean",
                        "description": "When false (default), drop products whose variants are all out-of-stock.",
                        "default": false
                    },
                    "minPrice": {
                        "title": "Min price",
                        "minimum": 0,
                        "maximum": 1000000,
                        "type": "number",
                        "description": "Drop products whose lowest variant price is below this threshold."
                    },
                    "maxPrice": {
                        "title": "Max price",
                        "minimum": 0,
                        "maximum": 1000000,
                        "type": "number",
                        "description": "Drop products whose lowest variant price is above this threshold."
                    },
                    "vendorContains": {
                        "title": "Vendor name contains",
                        "type": "string",
                        "description": "Only emit products whose vendor name contains this substring (case-insensitive)."
                    },
                    "productTypeContains": {
                        "title": "Product type contains",
                        "type": "string",
                        "description": "Only emit products whose `product_type` (Shopify taxonomy) contains this substring."
                    },
                    "tagAnyOf": {
                        "title": "Tag allowlist (any of)",
                        "type": "array",
                        "description": "Only emit products whose `tags` list contains at least one of these (case-insensitive substring match).",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "tagNoneOf": {
                        "title": "Tag blocklist",
                        "type": "array",
                        "description": "Drop products whose `tags` contains any of these substrings.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "titleContains": {
                        "title": "Title contains",
                        "type": "string",
                        "description": "Only emit products whose title contains this substring (case-insensitive)."
                    },
                    "onSaleOnly": {
                        "title": "On-sale products only",
                        "type": "boolean",
                        "description": "Only emit products with at least one variant where `compare_at_price` > `price` (i.e. discounted).",
                        "default": false
                    },
                    "minDiscountPercent": {
                        "title": "Min discount %",
                        "minimum": 0,
                        "maximum": 99,
                        "type": "integer",
                        "description": "Only emit products whose discount (`comparePrice` vs `price`) is at least this percentage. e.g. `30` = at least 30% off."
                    },
                    "createdSince": {
                        "title": "Created since (ISO YYYY-MM-DD)",
                        "type": "string",
                        "description": "Drop products created (`created_at`) before this date. Empty = no lower bound."
                    },
                    "updatedSince": {
                        "title": "Updated since (ISO YYYY-MM-DD)",
                        "type": "string",
                        "description": "Drop products updated (`updated_at`) before this date. Empty = no lower bound."
                    },
                    "skuContains": {
                        "title": "SKU contains",
                        "type": "string",
                        "description": "Only emit products with at least one variant whose SKU contains this substring (case-insensitive)."
                    },
                    "useApifyProxy": {
                        "title": "Use Apify proxy",
                        "type": "boolean",
                        "description": "Route requests through Apify proxy. Most Shopify stores work without proxy from datacenter IPs. The actor automatically falls back to Apify proxy on the first failure regardless of this setting.",
                        "default": false
                    },
                    "requestDelaySecs": {
                        "title": "Delay between page fetches (seconds)",
                        "minimum": 0,
                        "maximum": 10,
                        "type": "integer",
                        "description": "Pause between successive page fetches per store. Lower = faster, higher = more polite.",
                        "default": 1
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
