# Shopify Product Scraper — Prices, Inventory & Variants (`myworkingmemory/shopify-store-extractor`) Actor

Export public Shopify products, prices, variants, SKUs and availability. Optional published inventory, product panels and recommendations, charged when returned. JSON/CSV/Excel, market context and coverage reports. From $0.70/1,000 products. No Shopify API key.

- **URL**: https://apify.com/myworkingmemory/shopify-store-extractor.md
- **Developed by:** [Myworkingmemory LLC](https://apify.com/myworkingmemory) (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.70 / 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 Product Scraper — Prices, Inventory & Variants

Turn public Shopify storefronts into structured product data for price monitoring, assortment research, supplier catalog analysis and AI shopping workflows. Extract an entire accessible catalog, a collection, or individual product URLs. Export JSON, CSV, Excel or XML, or call the Actor through the Apify API.

**From $0.70 per 1,000 saved products with paid-plan discounts; $1 per 1,000 on the Free tier.** Published variants are included in the product price. No subscription, Shopify API key, proxy purchase or AI model fee is required. Optional extras are off by default and charged only when returned. Standard run platform usage is included in event pricing.

### Start in under a minute

1. Enter one or more public Shopify store, collection or product URLs.
2. Choose a maximum product count. Start with 10–100 products.
3. Run the Actor and inspect the Products dataset. Download your preferred format.
4. Check `SUMMARY` in the key-value store for coverage, limits, warnings and inaccessible stores.

```json
{
  "startUrls": [{ "url": "https://www.allbirds.com" }],
  "maxProducts": 100
}
```

### Run daily price and availability checks

Turn a successful test into repeat catalog snapshots for competitor price checks, assortment research or availability tracking. Start with a [tested example](https://apify.com/myworkingmemory/shopify-store-extractor/examples), then use the store or collection you actually need.

1. **Save your tested input as an Apify task.** Choose your product limit, keep unnecessary extras off, and set a maximum charge per run; for a base-only 100-product test, $0.11 covers the listed event charges on every tier.
2. **Schedule that task.** In Apify Console, open **Schedules → Create new**, choose daily and your timezone, then add your saved task. [Schedule setup guide](https://docs.apify.com/actors/running/schedules).
3. **Keep each snapshot or send it to your spreadsheet.** Preserve `recordKey`, `scrapedAt` and currency so successive observations can be compared; use the recipes below to move the data automatically.

At the Free-tier rate, 100 returned products once daily for 30 days cost **$3.0015 in Actor events**, including startup, with extras off; fewer returned products cost less. Post-run storage/data access and any external integration charges are additional. See [Pricing](#pricing) for paid-plan discounts and extras.

#### Send each scheduled snapshot to Google Sheets

**n8n:** connect your Apify account, add **On new Apify Event**, select your saved task and the successful-run event, then add **Get Dataset Items** using that run's `defaultDatasetId`; send the returned items to a Google Sheets append-row action. [Official n8n setup](https://docs.apify.com/integrations/n8n).

**Zapier:** connect Apify, select **Finished task run** for the saved task, filter for `SUCCEEDED`, then **Fetch dataset items** using the completed run's `defaultDatasetId`; loop through the returned items and create a Google Sheets row for each. This receives completed scheduled runs without Zapier's short synchronous-run timeout. [Official Zapier setup](https://docs.apify.com/integrations/zapier).

For either recipe, map `recordKey`, `scrapedAt`, `title`, `currency`, `priceMin`, `priceMax` and `available` to sheet columns. Check `SUMMARY` for partial or limited coverage; an absent row in a capped or incomplete snapshot does not prove a product was removed. Compare the same market/currency and matching product keys across dates. Price-change comparisons and alerts are steps you add in your spreadsheet or automation; the Actor supplies the snapshots.

For other destinations, use run-finished webhooks or [Make](https://docs.apify.com/integrations/make) to connect your saved task to a database or another application.

**Already using code or AI?** Use the [API example](#api-example) for your application or scheduler, or connect an AI client using the [Actor's MCP configuration](https://apify.com/myworkingmemory/shopify-store-extractor/api/mcp).

### What you receive

Each product includes its ID, title, URL, handle, vendor, product type, description HTML, tags, options, images, timestamps and all variants exposed by the catalog endpoint. Variants include IDs, SKUs, prices, compare-at prices, availability, options, weight and barcodes when published. Missing fields remain null rather than invented.

Catalog prices are decimal strings in major currency units: `"19.95"` means 19.95 units. Direct-feed currency comes from storefront cart metadata and is labeled `market.currencyVerified=false`; context-aware GraphQL money includes its currency and is marked verified. Missing currency remains null. No user cart is modified. Recommendation prices retain their original Shopify Ajax values and `priceUnit`; `priceDecimal` converts Shopify hundredths to decimal major units, including JPY/KRW. Existing price fields retain their types. Locale paths such as `/en-us/` are supported. Currency query overrides are not supported. Set `countryCode` for explicit market prices; this uses the tokenless Storefront endpoint. Markets can change both prices and assortment. Purchasability may include backorders and does not imply physical inventory.

### Pricing

| Event | Price | When charged |
| --- | --- | --- |
| Product — Free | $0.001 | One unique saved product |
| Product — Bronze / Silver | $0.0009 / $0.0008 | One unique saved product |
| Product — Gold, Platinum, Diamond | $0.0007 | One unique saved product |
| Published inventory | $0.001 | One saved product with at least one explicit numeric count, including zero or signed merchant counts |
| Information panels | $0.001 | One saved product with nonempty supported information panels |
| Recommended product | $0.001 | Each related product returned inside a parent record |
| Run start | $0.00005 | Once per run within the supported memory range |

A base-only 1,000-product export costs $1.00005 on Free or $0.70005 on Gold. On Free, 100 products plus 20 returned inventory enrichments costs $0.12005. Three recommendations on each of 100 products add $0.30. The Pricing tab is authoritative for effective prices and any scheduled change. Missing optional information, duplicate base products and error summaries have no corresponding result event charge. Apify's standard post-run storage and data-access charges may apply separately.

Set Apify's **maximum charge per run** to bound your spend. Set `maxProducts` to cap base products across all URLs. Optional events count toward the same monetary budget. Budget is reserved before optional requests. Unaffordable extras are omitted and labeled; cheaper base products can continue. The Actor stops when another base product is unaffordable; saved results remain accessible. A recommendation is billed per parent record, even if another product recommends the same item.

### Input reference

| Field | Default | Meaning |
| --- | --- | --- |
| `startUrls` | Required | 1–50 HTTPS storefront, collection or product URLs; strings or `{ "url": "…" }` objects |
| `maxProducts` | 100 | Global new-product cap, 0–100,000; 0 removes this output cap only |
| `query` | Empty | Case-insensitive substring of title, vendor, type or tags; only matching products are saved |
| `includeInventory` | false | Read explicit numeric counts from public product JSON |
| `includeInfoPanels` | false | Read labeled product-page details/accordions and supported accessible panels |
| `maxRecommendations` | 0 | Related recommendations per product, 0–10 |
| `maxPagesPerStore` | 400 | Maximum pages per input URL, 1–1,000; up to 250 product IDs per page; GraphQL details are fetched in batches of 10 |
| `maxProductsPerStore` | 0 | Optional product cap per input URL; 0 disables |
| `maxUnproductivePages` | 10 | Stop after consecutive catalog pages without keyword matches |
| `maxEnrichmentRequests` | 1,000 | Additional detail/inventory/panel/recommendation request cap |
| `maxRequests` / `maxRunSeconds` | 2,000 / 900 | Global request and extraction-time caps; SUMMARY explains limits |
| `includeStorefrontDetails` | false | Add public selling plans, detail availability and context-aware variant data where exposed; no extra event fee |
| `includeCollections` | false | Include the collection identity for collection inputs |
| `countryCode` | Unset | Explicit market country, for example `DK` or `DE` |
| `datasetId` | Unset | Also append results to an existing selected dataset, without a second product charge |
| `parentRunId` | Unset | Resume a finished compatible run; provide its read-only `parentDatasetId` and `parentStoreId` too |
| `proxyRecovery` | none | Paid recovery is disabled in this release; the acceptance test did not establish profitable additional coverage |

Filtering scans the listed catalog; it is not a search for new stores. Tokenless recovery cannot read tags, so filtered recovery reports partial query coverage. High page limits with narrow filters can take longer. Use collection URLs to narrow large catalogs efficiently.

### Useful workflows

**Compare brands:** supply multiple storefronts. Duplicate product IDs within the same storefront and locale are saved once. Failed stores are reported separately, and successful stores retain their results. Different domains/locales remain distinct because prices and assortments may differ.

**Enrich a product:** enable only the extras you need:

```json
{
  "startUrls": [{ "url": "https://www.allbirds.com" }],
  "maxProducts": 10,
  "includeInventory": true,
  "includeInfoPanels": true,
  "maxRecommendations": 3
}
```

### API example

Use your own Apify token in the Authorization header. No Shopify merchant token is needed.

```bash
curl --request POST \
  'https://api.apify.com/v2/acts/myworkingmemory~shopify-store-extractor/run-sync-get-dataset-items?format=json&timeout=120' \
  --header "Authorization: Bearer $APIFY_TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{"startUrls":[{"url":"https://www.allbirds.com"}],"maxProducts":10}'
```

For large catalogs, start asynchronously with `POST /v2/acts/myworkingmemory~shopify-store-extractor/runs`, poll the returned run ID, then download `/v2/datasets/{defaultDatasetId}/items`. Set `maxTotalChargeUsd` on the run request for your spending limit. Read `/v2/key-value-stores/{defaultKeyValueStoreId}/records/SUMMARY` for coverage.

### Coverage and reliability

The Actor starts with direct HTTP and bounded retries. If a public JSON endpoint is unavailable, it tries tokenless Storefront GraphQL before optional paid recovery. It validates public HTTPS redirects, continues beyond short and overlapping pages, and detects repeated pages. No browser is required. Paid proxy recovery remains disabled: neither tested route recovered additional products from the blocked acceptance store. The implementation retains a catalog-only $0.04 recovery ceiling and byte limits for future validated routes.

Not every Shopify store publishes `/products.json`. Password-protected stores, bot protection, headless storefronts, disabled public endpoints and restricted products may be inaccessible. Public access is required; private or password-protected products are not retrieved. If every store fails, the run fails with a diagnostic summary; mixed results are explicitly marked partial in `SUMMARY`. A successful run may intentionally stop at an output or operating limit; `SUMMARY.status=limited` and the per-store details explain this. A successfully read empty catalog or zero keyword matches can legitimately produce zero rows.

Shopify has a 25,000-object pagination ceiling and Ajax product details can stop at 250 variants. The Actor attempts bounded GraphQL variant pagination and creation-date partitions for whole-store traversal. Unsplittable partitions, limits and unavailable fields remain explicit. `source_exhausted` means the selected public source was traversed, not that private products or all markets were captured. High-variant recovery is not advertised as universally supported.

Inventory is **only** the count explicitly published by the merchant; stock availability alone never becomes a quantity. No cart-add probes or checkout activity occur. Information-panel support depends on theme markup; unsupported JavaScript-only content is not billed. Recommendations depend on Shopify's related-product endpoint and may be empty. Product data reflects the storefront response at the extraction time, not a guarantee of checkout price, complete warehouse inventory or future availability.

### Output and recovery

The **Products** view shows price ranges, purchasability and thumbnails; **Variants** expands SKUs and options. For a flat CSV through the dataset API, request `format=csv&unwind=variants&fields=recordKey,url,currency,variants,id,title,sku,priceDecimal,available&omit=variants`. Unwinding promotes variant fields to the row: `id` and `title` then identify the variant, while `recordKey` and `url` identify its product. Views help inspection; export parameters control downloadable columns.

Every row includes `recordKey`, source endpoint, market context and observation time. A compact example from an actual Allbirds test is shown below; values change over time:

```json
{
  "id": "7340901859408",
  "title": "Women's Allbirds Flip Flop - Dusty Pink",
  "currency": "USD",
  "priceMin": "25.0",
  "priceMax": "25.0",
  "available": true,
  "variantCount": 7,
  "variantCoverage": "source_exhausted"
}
```

Same-run restarts reconcile the output and charge journal before continuing. If a write or charge cannot be resolved safely, the run fails with a retained journal rather than risk duplicate billing. Inspect `FAILURE` and `SUMMARY`. For a finished run, copy `SUMMARY.resume` into the next input along with the same targets, query, extras and market. Select the parent dataset and checkpoint store to grant read-only access. Increase output limits if needed. The child emits new rows, skips previously saved keys, and never retries parent charges. It does not automatically combine the two default datasets; use `datasetId` when a shared append destination is wanted. Append failures preserve the default dataset and a recoverable journal.

### Support

Open an issue on this Actor with the public storefront URL, your run ID and the expected field. Do not include credentials or private customer data. Maintained by Myworkingmemory LLC. This is an independent tool, not an official Shopify product.

### Connect through MCP

Add this server URL to a compatible MCP client such as Claude or Cursor, then authorize your Apify account. It preloads this Actor as a tool:

[Apify MCP — Shopify Product Scraper](https://mcp.apify.com/?tools=myworkingmemory/shopify-store-extractor)

```text
https://mcp.apify.com/?tools=myworkingmemory/shopify-store-extractor
```

Connecting does not start a run. Ask your agent to review the input and pricing before running; the same prices, input requirements and limits apply. See the [Apify MCP setup guide](https://docs.apify.com/mcp).

### More tools from Myworkingmemory

- [Email Verifier](https://apify.com/myworkingmemory/email-verifier-bulk) — Verify email lists or Apify datasets; limited keyless pilot and BYOK options.
- [PDF & Word Metadata Cleaner](https://apify.com/myworkingmemory/document-metadata-cleaner) — Inspect metadata and create a separately verified cleaned copy.
- [Curated Finds](https://apify.com/myworkingmemory/software-library-search) — Discover curated GitHub tools and Hugging Face models.

Each Actor has its own inputs and pricing; follow its README before running. [Browse all our Actors](https://apify.com/myworkingmemory).

# Actor input Schema

## `startUrls` (type: `array`):

1–50 public Shopify store, collection or product URLs as strings or {"url":"https://store.com"} objects. Bare domains and locale paths are accepted. Invalid destinations are isolated in the coverage report. No Shopify API key required.

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

Global new-product cap across inputs. 0 removes this output cap; page, request, time and monetary limits still apply.

## `query` (type: `string`):

Case-insensitive match against title, vendor, product type and tags. Scans catalog pages and only bills matching saved products.

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

Read numeric inventory counts only when exposed in public product JSON. Unknown counts are never inferred from availability and are not billed.

## `includeInfoPanels` (type: `boolean`):

Extract labeled details/accordions and supported accessible panels from product HTML. Theme coverage varies; empty results are not billed.

## `maxRecommendations` (type: `integer`):

0 disables recommendations. Reads Shopify related-product recommendations, deduplicated per parent product.

## `maxPagesPerStore` (type: `integer`):

Safety cap for pagination, 250 requested products/page. SUMMARY reports if this cap is reached.

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

0 disables this cap. A capped input does not prevent remaining input URLs from running.

## `maxUnproductivePages` (type: `integer`):

Stops unproductive filtered scans with an explicit limited status. Overlapping outputs do not prematurely terminate pagination.

## `maxEnrichmentRequests` (type: `integer`):

Limits optional product-detail, inventory, panel and recommendation requests. Unavailable enrichment is not charged.

## `maxRequests` (type: `integer`):

Bounds catalog and enrichment HTTP operations, independently of output count. Retries remain separately bounded.

## `maxRunSeconds` (type: `integer`):

Stops requesting new pages after this elapsed time and saves partial results. Apify run timeout also applies.

## `includeStorefrontDetails` (type: `boolean`):

Fetch public product details, selling plans and tokenless GraphQL variant/price context where available. No extra event fee; subject to enrichment limits.

## `includeCollections` (type: `boolean`):

Include collection identity when extracting a collection. This does not discover every collection containing a product.

## `countryCode` (type: `string`):

Optional ISO country code, such as DK or DE. Uses tokenless Storefront queries with explicit market context; availability and assortment may differ.

## `datasetId` (type: `string`):

Optional existing dataset ID or name. Also writes the default run dataset. Appending does not charge another product event.

## `parentRunId` (type: `string`):

Parent run ID from SUMMARY.resume. Also select its dataset and key-value store below. Targets, market, query and extras must match; output limits may increase.

## `parentDatasetId` (type: `string`):

Select the parent run dataset from SUMMARY.resume. Previously saved product keys are not charged again in the child run.

## `parentStoreId` (type: `string`):

Select the parent key-value store from SUMMARY.resume. Read-only access is used for checkpoints; parent charges are never retried.

## `proxyRecovery` (type: `string`):

Paid proxy routes are disabled in this release: the acceptance test did not recover additional products profitably. Direct HTTP and tokenless GraphQL recovery are active.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.allbirds.com"
    }
  ],
  "maxProducts": 100,
  "query": "",
  "includeInventory": false,
  "includeInfoPanels": false,
  "maxRecommendations": 0,
  "maxPagesPerStore": 400,
  "maxProductsPerStore": 0,
  "maxUnproductivePages": 10,
  "maxEnrichmentRequests": 1000,
  "maxRequests": 2000,
  "maxRunSeconds": 900,
  "includeStorefrontDetails": false,
  "includeCollections": false,
  "proxyRecovery": "none"
}
```

# Actor output Schema

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

No description

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

No description

# 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 = {
    "startUrls": [
        {
            "url": "https://www.allbirds.com"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("myworkingmemory/shopify-store-extractor").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 = { "startUrls": [{ "url": "https://www.allbirds.com" }] }

# Run the Actor and wait for it to finish
run = client.actor("myworkingmemory/shopify-store-extractor").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 '{
  "startUrls": [
    {
      "url": "https://www.allbirds.com"
    }
  ]
}' |
apify call myworkingmemory/shopify-store-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,myworkingmemory/shopify-store-extractor"
        }
    }
}
```

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/V08aGsG6GhfDb6elb/builds/f1mpB3dKgS3LjwRAt/openapi.json
