Use Shopify Store Catalog & Pricing Extractor with Python
Extract a Shopify store's product catalog with titles, prices, compare-at prices, variants, SKUs, images and stock availability from any custom or myshopify.com domain.
1. Choose the data you need
Review the published README for supported collection modes, examples, and limits. The recipe below uses the current published input definition.
2. Prepare a source-based input
This JSON contains published prefills and required-field defaults. Review every value for your task before running it; it is not a promise of successful collection.
{
"available": "any",
"collectionHandles": [],
"currency": "USD",
"flattenVariants": false,
"includeDetails": false,
"maxItems": 3,
"maxPages": 100,
"mode": "catalog",
"productHandles": [],
"startUrls": [],
"storeUrls": [
"https://deathwishcoffee.com"
]
}
Download input.example.json and save your reviewed copy as input.json.
| Field | Type | Required | Description |
|---|---|---|---|
mode | string | required | What to scrape. `catalog` walks the public product feed, `collection` walks specific collections, `product` fetches exact product handles, `search` uses the storefront search suggestions, `collections` lists collection metadata, and `auto` detects the type of each URL in `startUrls`. |
storeUrls | array | optional | Store domains or URLs, e.g. `deathwishcoffee.com` or `https://www.allbirds.com`. Accepts custom domains and `*.myshopify.com`. A product or collection URL is reduced to its store for catalog/collections/search modes. |
startUrls | array | optional | Store, collection or product URLs. In `auto` mode each URL selects its own job: `/products/<handle>` fetches one product, `/collections/<handle>` fetches a collection, any other store URL fetches the catalog. In the other modes these URLs add stores and, for collection/product modes, their handles. |
collectionHandles | array | optional | Collection handles or collection URLs, e.g. `new-arrivals`, `sale`, or `https://store.com/collections/sale`. Handles are applied to every store in `storeUrls`; a full collection URL is applied to its own store. |
productHandles | array | optional | Product handles or product URLs, e.g. `dark-roast-coffee` or `https://store.com/products/dark-roast-coffee`. Handles are applied to every store in `storeUrls`; a full product URL is applied to its own store. |
searchQuery | string | optional | In-store search term. Shopify's public suggest endpoint returns at most 10 products per store and has no pagination. |
currency | string | optional | ISO 4217 code to pin prices to, e.g. `USD`, `EUR`, `GBP`. Use `store` to use the store's base currency from `/meta.json`. Pinning is important because Shopify localizes prices by IP. |
country | string | optional | Two-letter ISO country code passed as `?country=` to the storefront, e.g. `US`, `GB`, `DE`. |
vendor | string | optional | Keep products whose vendor contains this text (case-insensitive). |
productType | string | optional | Keep products whose product type contains this text (case-insensitive). |
tag | string | optional | Keep products with at least one tag containing this text (case-insensitive). |
minPrice | number | optional | Drop products whose lowest variant price is below this value. |
maxPrice | number | optional | Drop products whose lowest variant price is above this value. |
available | string | optional | Keep all products, only products with at least one purchasable variant, or only sold-out products. |
maxItems | integer | optional | Hard cap on dataset rows across all stores. When `flattenVariants` is on, each variant row counts as one. |
maxPages | integer | optional | Page cap per product/collection feed. Each page holds up to 250 items and Shopify refuses offsets above 25,000, so the effective maximum is 100. |
includeDetails | boolean | optional | Fetch `/products/{handle}.json` for each emitted product to add barcode, weight/grams and inventory fields. Costs one extra request per product and is off by default. Product mode always uses the detail endpoint. |
flattenVariants | boolean | optional | Emit one `recordType: variant` row per variant instead of one product row with nested variants. Variant and product IDs are de-duplicated. |
proxyConfiguration | object | optional | Leave empty to fetch directly. After a 403 or 429 block the actor retries through Apify's datacenter proxy (AUTO) automatically. If you set this, your configuration is used for that retry instead of AUTO; direct requests are still tried first. |
3. Start an Actor run
Set APIFY_TOKEN in your environment. Python 3.10 or newer is sufficient; this recipe uses no third-party packages.
Execution may incur charges. Review current pricing on Apify. The request asks for a 120-second timeout and a charge limit; these settings are subject to Apify’s pricing and do not guarantee an all-inclusive spending cap.
import json
import os
import urllib.request
# Save the schema-derived example as input.json; review and edit it first.
with open("input.json", encoding="utf-8") as stream:
actor_input = json.load(stream)
token = os.environ["APIFY_TOKEN"]
request = urllib.request.Request(
"https://api.apify.com/v2/acts/MaKZQdevxgpAmpJ8l/runs?timeout=120&maxTotalChargeUsd=0.50",
data=json.dumps(actor_input).encode("utf-8"),
headers={"Authorization": "Bearer " + token, "Content-Type": "application/json"},
method="POST",
)
# This starts a potentially billable run. Do not automatically retry this POST.
with urllib.request.urlopen(request, timeout=40) as response:
run = json.load(response)["data"]
print("Run ID:", run["id"])
print("Status:", run["status"])
# Inspect and download results in Apify Console once the run succeeds.
4. Inspect the actual results
Open the run in Apify Console and wait for a successful completion. Use the published output schema to locate results and the dataset schema to understand declared views. Missing or optional record fields must not be treated as guaranteed values.
Dataset rows for products, variants or collections, plus a per-store run summary record.
Questions before you run
Which inputs are required?
The published required fields are mode
What does this guide verify?
The fields, prefills, and schema links are rendered from the published build. This is a usage recipe, not a paid live extraction test. Source availability and collection results can vary.
What if the run request times out?
Check Apify Console before retrying. The first request may already have created a run. Do not automatically repeat a run-creation POST.
Generated from source build rfdRrnEMOeqFiOPHE and its README and schemas. Source changes regenerate this guide; no third-party editorial claims are inferred.