Nimbryxo Studio

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.

FieldTypeRequiredDescription
modestringrequiredWhat 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`.
storeUrlsarrayoptionalStore 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.
startUrlsarrayoptionalStore, 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.
collectionHandlesarrayoptionalCollection 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.
productHandlesarrayoptionalProduct 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.
searchQuerystringoptionalIn-store search term. Shopify's public suggest endpoint returns at most 10 products per store and has no pagination.
currencystringoptionalISO 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.
countrystringoptionalTwo-letter ISO country code passed as `?country=` to the storefront, e.g. `US`, `GB`, `DE`.
vendorstringoptionalKeep products whose vendor contains this text (case-insensitive).
productTypestringoptionalKeep products whose product type contains this text (case-insensitive).
tagstringoptionalKeep products with at least one tag containing this text (case-insensitive).
minPricenumberoptionalDrop products whose lowest variant price is below this value.
maxPricenumberoptionalDrop products whose lowest variant price is above this value.
availablestringoptionalKeep all products, only products with at least one purchasable variant, or only sold-out products.
maxItemsintegeroptionalHard cap on dataset rows across all stores. When `flattenVariants` is on, each variant row counts as one.
maxPagesintegeroptionalPage 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.
includeDetailsbooleanoptionalFetch `/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.
flattenVariantsbooleanoptionalEmit one `recordType: variant` row per variant instead of one product row with nested variants. Variant and product IDs are de-duplicated.
proxyConfigurationobjectoptionalLeave 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.