# Shopify Products Scraper - Variants, Stock & Store Leads (`tinyrex/shopify-products-scraper`) Actor

Shopify products scraper: export prices, variants, SKUs, stock and inventory to CSV/JSON. Store mode: one lead row per store (theme, installed apps, socials); filter by app, theme, email/phone or catalog size (filtered free). $0.70 per 1,000 products; non-Shopify, blocked or filtered results free.

- **URL**: https://apify.com/tinyrex/shopify-products-scraper.md
- **Developed by:** [TinyRex](https://apify.com/tinyrex) (community)
- **Categories:** E-commerce, Lead generation, Automation
- **Features:** Limited permissions
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.56 / 1,000 products

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

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: export products, prices, variants, stock and store leads

**Shopify products scraper: export every product from any Shopify store to CSV, Excel or JSON in seconds, or collect store leads (theme and installed apps) in Store mode.** Enter a store domain, a collection URL or a product URL and get prices, discounts, variants (size, color), SKUs, stock status, images, tags and descriptions as one clean table. It reads the public product feed every Shopify store provides (no browser, no login). **$0.70 per 1,000 products; non-Shopify, blocked or password-protected stores and products removed by your filters are free.**

### What you get from the Shopify Products Scraper

- **The full catalog of any Shopify store**: title, vendor, product type, tags, price, compare-at price, discount %, variants with SKU and availability, options, images, dates and description. Works on **headless stores** too: the scraper finds the store's `*.myshopify.com` domain and reads the feed from there, and it continues through collections for stores above Shopify's 25,000-product listing limit.
- **Spreadsheet-ready output**: one row per product (variants nested) or **one row per variant** (flat, best for price tracking), plus optional stock quantity and barcode per variant when the store exposes them.
- **Shopify store leads in bulk (Store mode)**: paste a list of store domains and get **one row per store**: store name, country, currency, catalog size, price range, share of products on sale and in stock, top vendors, product types and tags, products launched in the last 30 days, the **Shopify theme** (name, version, Theme Store ID) and **installed apps** detected on the storefront (Klaviyo, Judge.me, Yotpo, Recharge, Rebuy, Gorgias, Afterpay, Meta Pixel and 70+ more), plus the social profiles and public emails/phones linked on the homepage.
- **Price and new-product monitoring built in**: schedule it with *Monitoring mode* and each run returns only new products, or new products plus **price and stock changes** with the previous values.

### Sample output (JSON)

```json
{
  "storeName": "Allbirds",
  "currency": "USD",
  "productId": 7205191974992,
  "url": "https://www.allbirds.com/products/mens-dasher-nz-anthracite",
  "title": "Men's Dasher NZ - Anthracite (Dark Anthracite Sole)",
  "vendor": "Allbirds",
  "productType": "Shoes",
  "price": 140,
  "compareAtPrice": null,
  "onSale": false,
  "available": true,
  "availableVariants": 3,
  "variantsCount": 13,
  "options": [{ "name": "Size", "values": ["8", "8.5", "9"] }],
  "featuredImage": "https://cdn.shopify.com/s/files/1/1104/4168/files/...png",
  "variants": [{ "id": 41271176757328, "title": "8", "sku": "A12417M080", "price": 140, "available": false }],
  "publishedAt": "2026-08-24T09:53:01-07:00"
}
```

Download as **JSON, CSV, Excel or HTML**, or send it to Google Sheets, Make, Zapier, n8n, Slack, webhooks or the Apify API. Each run also writes a `STORES` report (status per input: `ok`, `not_shopify`, `blocked`, `password_protected`, `unreachable`, `not_found`, plus the method used) and a `SUMMARY` record to the key-value store.

### How to configure the Shopify Products Scraper

1. Add **Shopify stores, collections or products** (one per line): a domain (`allbirds.com`), a collection (`https://www.allbirds.com/collections/mens`) or a single product (`https://colourpop.com/products/lip-locked`).
2. Optional filters: keywords, exclude keywords, vendors, product types, price range, only in stock, only on sale, minimum discount %, published in the last N days.
3. Pick **products**, **variants** or **stores** output (one summary row per store), then run, or schedule it with *Monitoring mode* on.

#### Example input: in-stock products from two stores

```json
{
  "stores": ["deathwishcoffee.com", "https://www.allbirds.com/collections/mens"],
  "outputMode": "products",
  "onlyAvailable": true,
  "maxProductsPerStore": 500
}
```

| Setting | Default | Notes |
|---|---|---|
| stores | `deathwishcoffee.com` | Store domain, `*.myshopify.com` domain, collection URL or product URL |
| maxProductsPerStore | 50 | `0` = all products |
| outputMode | products | `products` (variants nested), `variants` (one row per variant) or `stores` (one store-leads row per store) |
| keywords / excludeKeywords | none | Match title, tags, vendor or type |
| vendors / productTypes | none | Partial match, e.g. `Allbirds`, `Shoes` |
| minPrice / maxPrice | none | In the store currency |
| onlyAvailable / onlyOnSale | false | In-stock only / discounted only |
| minDiscountPercent | 0 (off) | Keep products whose compare-at discount is at least this %; below the cut is free |
| publishedWithinDays | 0 (any) | Only recently published products |
| descriptionFormat | text | `text`, `html`, `both` or `none` |
| includeInventory | false | Stock quantity, inventory policy and barcode where exposed (separate event) |
| monitorMode / stateKey | off / default | `new` or `changes`; use one state key per schedule |
| onlyIfUsesApps / excludeIfUsesApps | none | Store mode: keep or skip stores by detected app or category, e.g. `Klaviyo`, `subscriptions` (skipped stores free) |
| onlyIfThemes | none | Store mode: keep stores on these themes, e.g. `Dawn`, `Prestige` |
| onlyWithEmail / onlyWithPhone | false | Store mode: keep only stores with a homepage `mailto:` email / `tel:` phone (skipped stores free) |
| minCatalogSize / maxCatalogSize | none | Store mode: keep stores whose catalog size is in this range (skipped stores free) |
| maxConcurrency | 5 | Stores in parallel |
| proxyConfiguration | no proxy | Turn on Apify Proxy if a store blocks or rate-limits |

### Store mode: Shopify store leads and catalog stats in bulk

Set **Output** to **Store** and add as many store domains as you like. The Actor scans each whole catalog (up to 25,000 products per store; Max products and Monitoring are ignored in this mode) and saves one row per store. Your filters still apply, so `"keywords": ["vegan"]` gives the count, price range and vendors of vegan products only.

```json
{ "stores": ["deathwishcoffee.com", "allbirds.com", "gymshark.com"], "outputMode": "stores" }
```

Real row (trimmed) from a test run on 29 Oct 2026:

```json
{
  "storeUrl": "https://allbirds.com",
  "storeName": "Allbirds",
  "myshopifyDomain": "weareallbirds.myshopify.com",
  "currency": "USD",
  "storeCountry": "US",
  "publishedProductsCount": 356,
  "productsMatched": 356,
  "minPrice": 0.8, "medianPrice": 110, "avgPrice": 108.23, "maxPrice": 165,
  "onSalePercent": 4.2,
  "inStockPercent": 98,
  "vendorsCount": 2,
  "topProductTypes": [{ "name": "Shoes", "products": 344 }, { "name": "Apparel", "products": 3 }],
  "productsPublishedLast30Days": 0,
  "newestProductPublishedAt": "2026-09-25T23:58:13.000Z",
  "themeSchemaName": "allbirds-theme", "themeVersion": "1.231.12", "themeFromThemeStore": false,
  "apps": [{ "name": "Attentive", "category": "email-sms" }, { "name": "Redo", "category": "shipping-returns" }, { "name": "Triple Whale", "category": "analytics" }],
  "appsCount": 6,
  "homepageTitle": "Allbirds: Comfortable, Sustainable Shoes & Apparel",
  "emails": ["help@allbirds.com"],
  "socialLinks": { "instagram": "https://www.instagram.com/allbirds", "tiktok": "https://www.tiktok.com/@weareallbirds", "facebook": "https://www.facebook.com/weareallbirds" }
}
```

#### Shopify theme and app detection (Store mode)

Every store row also says which theme and apps the store runs, read from the same homepage request (no extra cost):

- `themeName`, `themeSchemaName` (the base theme, for example `Dawn`), `themeVersion`, `themeStoreId` and `themeFromThemeStore` (false for custom or edited themes with no Theme Store ID).
- `apps`: well-known apps found on the storefront, each with a category: email-sms, reviews, subscriptions, loyalty, upsell, search, wishlist, support, page-builder, payments, shipping-returns, translation, analytics and affiliate. `appCategories` and `appsCount` summarise them.
- `appPixelsCount`: how many app web pixels the store loads (Shopify does not publish their names).
- `headless`: true when the storefront is a custom frontend (Hydrogen, Next.js) instead of a Shopify theme.

Detection only sees apps that load on the homepage, so backend-only apps (ERP, inventory, checkout-only) are not listed. Missing an app you need? Open an issue and it gets added.

Real row: Death Wish Coffee runs a customised **Dawn 10.0.0** with Klaviyo, Bazaarvoice, Ordergroove, Smile.io, Rebuy, Gorgias, NoFraud and Google Analytics 4 (test run, 1 Nov 2026).

#### Filter Shopify stores by app or theme (Store mode)

Find prospects in a big domain list without paying for the rest:

- **onlyIfUsesApps**: keep stores where at least one of these apps or categories is detected, e.g. `["Recharge", "Skio"]` or `["subscriptions"]`.
- **excludeIfUsesApps**: skip stores that already use an app, e.g. `["email-sms"]` to find stores with no email/SMS tool (leads for an email marketing agency), or `["Judge.me", "reviews"]` for stores with no reviews app.
- **onlyIfThemes**: keep stores on a theme or base theme, e.g. `["Dawn"]` or `["Prestige", "Impulse"]` (useful for theme developers and app builders).

```json
{ "stores": ["deathwishcoffee.com", "allbirds.com", "gymshark.com"], "outputMode": "stores", "excludeIfUsesApps": ["Klaviyo"] }
```

The homepage is checked first, so stores that do not match are skipped **before** the catalog scan and are **free**. They are listed with status `filtered` and the reason in the `STORES` record.

#### Filter Shopify stores by contact or catalog size (Store mode)

For sales and agency outreach, keep only stores that look worth contacting:

- **onlyWithEmail**: keep stores with at least one homepage `mailto:` email.
- **onlyWithPhone**: keep stores with at least one homepage `tel:` phone.
- **minCatalogSize** / **maxCatalogSize**: keep stores whose published product count is in this range.

Email and phone filters run after the homepage fetch and before the catalog scan (same as app/theme filters). Catalog size uses `publishedProductsCount` from store meta when available (also before the scan). If meta has no count, the store is crawled as usual and then filtered on products found, with **no charge** and no dataset row. Filtered stores are free either way.

```json
{ "stores": ["deathwishcoffee.com", "allbirds.com"], "outputMode": "stores", "onlyWithEmail": true, "minCatalogSize": 50 }
```

Each store row costs the same as 5 product rows ($0.0035 per store, $3.50 per 1,000 stores). Non-Shopify, blocked and password-protected sites stay free. Emails and phones are only the ones the store itself links on its homepage (`mailto:` / `tel:`), usually support addresses.

### Common use cases

- **Competitor price and inventory monitoring**: track a rival's prices, discounts, stock and inventory daily and get only the changes.
- **Ecommerce market research**: catalog size, price ranges, vendors and product types across many DTC brands.
- **Product feeds and dropshipping catalogs**: pull a supplier's full catalog with SKUs and images into a spreadsheet or your own store.
- **Shopify store lists for sales teams (Store mode)**: qualify a list of DTC brands by catalog size, prices, launches and social profiles before outreach.
- **Lead generation for ecommerce agencies and apps**: find which Shopify brands launch new products or run sales, then reach out.

### Pricing (pay per product, failures free)

- **Product** (`product`): **$0.0007 per product** saved to your dataset ($0.70 per 1,000; per variant row in variant mode), $0.00063 on Silver and $0.00056 on Gold.
- **Store row** (Store mode): charged as 5 `product` events, so **$0.0035 per store** (less with your tier discount).
- **Stock details** (`inventory-details`): $0.0005 per product, only with *Add stock quantity and barcode* on and only where stock data was actually found.
- **Free:** stores that are not Shopify, blocked or password-protected stores, unreachable sites and filtered-out products.

Set a maximum cost per run and the Actor stops gracefully when it is reached. See the *Pricing* tab for current tier discounts.

### Limitations

- Only data the store publishes in its public storefront is available. Reviews, sales numbers and cost prices are not.
- Stock quantity is only available when the store exposes it. Many stores do not.
- Some headless stores hide their Shopify domain. These are reported as `not_shopify` or `blocked` and are not charged.
- For stores with more than 25,000 products, products that are not in any public collection can be missing.

### Use with AI agents (MCP)

This Actor works as a tool for AI agents through the **Apify MCP server** at `https://mcp.apify.com`. Connect Claude, Cursor, VS Code, n8n or any other MCP client to `https://mcp.apify.com?tools=tinyrex/shopify-products-scraper` and ask, for example: *"Export all products under $50 from allbirds.com"*. Results come back as structured JSON at the same pay-per-product price; failed inputs stay free.

📘 **Step-by-step guide with Python, JavaScript, curl and MCP examples:** [How to export all products from any Shopify store to CSV or JSON](https://emirmrkaljevic.github.io/tinyrex-data-tools/export-shopify-store-products-to-csv/)

### FAQ

**How do I export all products from a Shopify store?** Enter the store domain (for example `allbirds.com`) and set *Max products per store* to `0`. The Actor reads the store's public product feed and gives you every product as CSV, Excel or JSON, with variants nested or as separate rows.

**How do I get a list of Shopify stores with their stats and social links?** Set *Output* to *Store* and paste the domains. You get one row per store with catalog size, median price, discounts, stock share, top vendors and product types, new products in the last 30 days, and the Instagram, TikTok, Facebook, YouTube, Pinterest and X profiles linked on the homepage. Use the [Tech Stack Detector](https://apify.com/tinyrex/tech-stack-detector) first if you still need to find out which domains run Shopify.

**Can I scrape a Shopify store I don't own?** Yes, for public product data. Every Shopify store publishes its product catalog for browsers, apps and search engines; this Actor reads that public data only. It does not log in, does not access customer or order data, and does not bypass passwords. Use the data in line with the store's terms and your local law.

**How do I track a competitor's Shopify prices?** Set *Monitoring mode* to *New products and price/stock changes*, schedule the Actor daily, and connect an integration (email, Slack, Google Sheets). The first run is the baseline; later runs return only new products and changes, with `previousPrice` and `previousAvailable`.

**How do I know if a website is a Shopify store?** Just add it: non-Shopify sites are reported as `not_shopify` in the `STORES` record and are free. For a long domain list, run the [Tech Stack Detector](https://apify.com/tinyrex/tech-stack-detector) with its `onlyIfUses` filter set to `Shopify` first.

**Does it work on headless Shopify stores?** Usually yes. The scraper finds the store's `*.myshopify.com` domain and reads the feed from there, and switches to it automatically if the storefront starts blocking. You can also pass the `xxx.myshopify.com` domain directly.

**How fast is it?** In our test, 30 stores with about 66,000 products took under 2 minutes. Speed depends on store size and response times.

**Which theme and apps does a Shopify store use?** Set *Output* to *Store*. Each row has the theme name, base theme and version, and a list of detected apps with categories (email/SMS, reviews, subscriptions, loyalty, upsell, support, payments, analytics and more). To keep only matching stores, use *Only stores using these apps*, *Skip stores using these apps* or *Only stores on these themes*; non-matching stores are skipped before the catalog scan and are free.

### Related actors

- [WooCommerce Products Scraper](https://apify.com/tinyrex/woocommerce-products-scraper): The same product export for WooCommerce stores.
- [Tech Stack Detector](https://apify.com/tinyrex/tech-stack-detector): Find out which domains are Shopify stores first (`onlyIfUses: Shopify`), then feed them here.
- [Contact Details Extractor](https://apify.com/tinyrex/contact-details-extractor): Company emails, phones and social links for the brands you found.
- [ATS Jobs Scraper](https://apify.com/tinyrex/ats-jobs-scraper): See which brands are hiring: jobs from Greenhouse, Lever, Ashby, Personio and more.

### Missing a field?

If a field you need is missing or wrong, please open an issue on the Issues tab. I read every issue and usually reply the same day.

# Actor input Schema

## `stores` (type: `array`):

Store domains (allbirds.com), store URLs, collection URLs (https://store.com/collections/sale) or product URLs (https://store.com/products/handle). Headless stores are supported when their \*.myshopify.com domain can be found. Inputs that are not Shopify stores are skipped and not charged.

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

Maximum number of products to save per input (after filters). 0 = all products.

## `outputMode` (type: `string`):

Product: one row per product with a nested variants list. Variant: one flat row per variant (size/color), easiest for spreadsheets and price tracking. One charge per row. Store: one store-leads row per store (catalog size, price range, discounts, stock, top vendors/types/tags, new products in 30 days, social profiles, public emails/phones from the homepage), scans the whole catalog (up to 25,000 products) and ignores Max products and Monitoring; each store row costs the same as 5 product rows.

## `keywords` (type: `array`):

Keep only products whose title, vendor, product type or tags contain any of these words (case-insensitive).

## `excludeKeywords` (type: `array`):

Drop products whose title or tags contain any of these words.

## `vendors` (type: `array`):

Keep only products from these vendors (partial match).

## `productTypes` (type: `array`):

Keep only these product types (partial match), e.g. Shoes, Coffee.

## `minPrice` (type: `integer`):

Lowest variant price must be at least this (store currency). Leave empty for no limit.

## `maxPrice` (type: `integer`):

Lowest variant price must be at most this (store currency). Leave empty for no limit.

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

Keep only products with at least one variant available for sale.

## `onlyOnSale` (type: `boolean`):

Keep only products with a compare-at price higher than the price (discounted).

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

Keep only products whose discount (compare-at vs price) is at least this percent. 0 = off. Products below the cut are free.

## `publishedWithinDays` (type: `integer`):

Keep only products published in the last N days. 0 = any time.

## `onlyIfUsesApps` (type: `array`):

Store mode only. Keep only stores where at least one of these apps or app categories is detected on the homepage, e.g. Klaviyo, Recharge, Judge.me, or a category: email-sms, reviews, subscriptions, loyalty, upsell, search, wishlist, support, page-builder, payments, shipping-returns, translation, analytics, affiliate. Partial, case-insensitive match. Non-matching stores are skipped before the catalog scan and are free.

## `excludeIfUsesApps` (type: `array`):

Store mode only. Skip stores where any of these apps or categories is detected, e.g. Klaviyo to find stores without an email tool (prospects for an email agency). Skipped stores are free.

## `onlyIfThemes` (type: `array`):

Store mode only. Keep only stores whose Shopify theme name or base theme matches, e.g. Dawn, Prestige, Impulse. Partial, case-insensitive match. Headless stores have no theme and are skipped (free).

## `onlyWithEmail` (type: `boolean`):

Store mode only. Keep only stores that link at least one mailto: email on the homepage. Checked after the homepage fetch and before the catalog scan. Filtered stores are free.

## `onlyWithPhone` (type: `boolean`):

Store mode only. Keep only stores that link at least one tel: phone on the homepage. Checked after the homepage fetch and before the catalog scan. Filtered stores are free.

## `minCatalogSize` (type: `integer`):

Store mode only. Keep only stores with at least this many published products. Uses the store meta count when available (before the catalog scan); otherwise checks products found after the scan and skips the charge. Filtered stores are free. Leave empty for no minimum.

## `maxCatalogSize` (type: `integer`):

Store mode only. Keep only stores with at most this many published products. Uses the store meta count when available (before the catalog scan); otherwise checks products found after the scan and skips the charge. Filtered stores are free. Leave empty for no maximum.

## `descriptionFormat` (type: `string`):

Product description as plain text, HTML, both, or none (smaller output).

## `includeInventory` (type: `boolean`):

Fetches each product page feed to add inventory quantity, inventory policy and barcode per variant, when the store exposes them. Slower (one extra request per product). Charged per product where stock data was found.

## `monitorMode` (type: `string`):

Off: return all matching products. New: only products not seen in previous runs. Changes: new products plus price, compare-at price or availability changes (with previous values). State is kept per store under the state key. The first monitoring run returns everything as the baseline.

## `stateKey` (type: `string`):

Name of the monitoring state. Use different keys for different schedules or filters.

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

How many stores are processed at the same time. Pages of one store are fetched politely one after another.

## `proxyConfiguration` (type: `object`):

Usually not needed. Use a proxy if a store blocks requests (HTTP 403/429).

## Actor input object example

```json
{
  "stores": [
    "deathwishcoffee.com"
  ],
  "maxProductsPerStore": 50,
  "outputMode": "products",
  "keywords": [],
  "excludeKeywords": [],
  "vendors": [],
  "productTypes": [],
  "onlyAvailable": false,
  "onlyOnSale": false,
  "minDiscountPercent": 0,
  "publishedWithinDays": 0,
  "onlyIfUsesApps": [],
  "excludeIfUsesApps": [],
  "onlyIfThemes": [],
  "onlyWithEmail": false,
  "onlyWithPhone": false,
  "descriptionFormat": "text",
  "includeInventory": false,
  "monitorMode": "off",
  "stateKey": "default",
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Products with prices, variants, stock and images.

## `stores` (type: `string`):

For every input: status (ok, not_shopify, blocked, password_protected...), method, store name, currency, products found/saved, notes.

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

Totals for the run.

## `storeRows` (type: `string`):

One summary row per store when Output is set to Store.

# 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 = {
    "stores": [
        "deathwishcoffee.com"
    ],
    "maxProductsPerStore": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("tinyrex/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 = {
    "stores": ["deathwishcoffee.com"],
    "maxProductsPerStore": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("tinyrex/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 '{
  "stores": [
    "deathwishcoffee.com"
  ],
  "maxProductsPerStore": 50
}' |
apify call tinyrex/shopify-products-scraper --silent --output-dataset

```

## MCP server setup

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