# Shopify Products Scraper: Prices, Variants & Stock (`lanternlane-data/shopify-store-products-scraper`) Actor

Scrape every product from any Shopify store: prices, sale prices, variants, SKUs, stock, images, tags and vendor, via the public products.json feed. Whole store or one collection. Tracks price and stock changes between runs. Fast, no browser, no login.

- **URL**: https://apify.com/lanternlane-data/shopify-store-products-scraper.md
- **Developed by:** [Lantern Lane Data](https://apify.com/lanternlane-data) (community)
- **Categories:** E-commerce, Lead generation
- **Stats:** 2 total users, 1 monthly users, 68.8% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 product or variant records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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: prices, variants, SKUs & stock from any Shopify store

### 🛍️ What is the Shopify Products Scraper?

Export **every product from any Shopify store** into a clean dataset: title, vendor, product type, tags, **price, compare-at (original) price, discount %, variants, SKUs, stock status**, images, description and dates. Paste store domains (or collection URLs) and get results in seconds.

It reads the store's **public `products.json` storefront feed**, the same JSON every Shopify store serves to browsers and apps. No browser, no login, no captcha, and usually no proxy, so it's **fast and very cheap to run**.

Schedule it and it becomes a **competitor price & stock monitor**: it remembers the last run and flags `isNew`, `priceChanged` (with `previousPrice`) and `availabilityChanged`, and can output **only what changed**.

- ✅ Any public Shopify store: `allbirds.com`, `colourpop.com`, `gymshark.com` ...
- ✅ Whole store or just one collection (`https://store.com/collections/sale`)
- ✅ One row per **product** (variants nested) or per **variant / SKU** (flat, CSV-friendly)
- ✅ Prices, compare-at prices, `onSale`, `discountPercent`, in-stock flags per variant
- ✅ Price & stock change tracking between runs, plus an "only changes" mode for alerts
- ✅ Filters: keywords, product types, vendors, in-stock only, on-sale only, price range, updated since
- ✅ Respects each store's robots.txt (stores that disallow the feed are skipped)
- ✅ Up to 25,000 products per store, ~250 products per request

### 🎯 What can I use it for?

- **Competitor price monitoring**: track competitors' prices, discounts and sell-outs daily.
- **Dropshipping & product research**: find best-sellers, new arrivals, price points and vendors in a niche.
- **Catalogue migration & backups**: export a store's catalogue (titles, images, variants, SKUs) to CSV/Excel.
- **Market research**: compare assortments and pricing across many DTC brands.
- **Deal & sale alerts**: run hourly with *Only discounted products* + *Only new / changed items*.
- **AI agents & apps**: predictable JSON via the Apify API, integrations or MCP.

### ⬇️ Input

| Field | Description |
|---|---|
| `storeUrls` (required) | Store domains or URLs. A `/collections/<handle>` URL limits the run to that collection. |
| `outputLevel` | `product` (default, variants nested) or `variant` (one flat row per variant/SKU). |
| `keywords` | Keep products whose title, type, vendor or tags contain any of these. |
| `productTypes` / `vendors` | Exact product types / vendors to keep. |
| `onlyAvailable` / `onlyOnSale` | Only in-stock / only discounted items. |
| `minPrice` / `maxPrice` | Price range in the store's currency. |
| `updatedSince` | `2026-10-01` or `7 days`. |
| `maxProductsPerStore` | Products read per store (default 1,000; `0` = all). |
| `maxResults` | Overall cap on output records (also caps cost). |
| `includeDescription` | Plain-text description (default on). |
| `trackChanges` / `onlyChanges` | Change tracking (default on) / output only new or changed items. |
| `stateStoreName` | Named store for tracking; use one per monitor. |

#### Example input

```json
{
  "storeUrls": ["allbirds.com", "https://colourpop.com/collections/lips"],
  "outputLevel": "variant",
  "onlyOnSale": true,
  "maxProductsPerStore": 0
}
```

### ⬆️ Output

Product mode (shortened):

```json
{
  "id": "allbirds.com-7340901859408",
  "storeName": "Allbirds",
  "title": "Women's Allbirds Flip Flop - Dusty Pink",
  "url": "https://allbirds.com/products/womens-allbirds-flip-flop-dusty-pink",
  "vendor": "Allbirds",
  "productType": "Shoes",
  "currency": "USD",
  "price": 25.0,
  "priceMax": 25.0,
  "compareAtPrice": 50.0,
  "onSale": true,
  "discountPercent": 50.0,
  "available": true,
  "variantCount": 7,
  "availableVariantCount": 3,
  "imageUrl": "https://cdn.shopify.com/s/files/1/1104/4168/files/A12513_26Q2_Allbirds-Flip-Flop-Dusty-Pink_PDP_LEFT.png",
  "variants": [{"variantId": "42146889039952", "title": "5", "sku": "A12513W050", "price": 25.0, "compareAtPrice": 50.0, "available": false}],
  "isNew": false,
  "priceChanged": true,
  "previousPrice": 30.0,
  "availabilityChanged": false
}
```

Variant mode adds `variantId`, `variantTitle`, `sku`, `option1-3`, `grams` and gives each variant its own price, sale and stock flags. See `sample_output.json` for full records. Console views: **Overview** (with images) and **Price & stock changes**.

`RUN_SUMMARY` in the default key-value store lists products read, records output and any error per store.

### 💰 How much does it cost?

**Free until 22 October 2026.** From then on it uses **pay-per-event** pricing: **$0.80 per 1,000 products or variants** (`product-result`, $0.0008 each) plus Apify's standard $0.00005 Actor start fee. Platform usage is included. Use the maximum-items limits or the run's maximum cost setting to cap spending.

### ⚠️ Notes & limits

- Works with stores running Shopify's standard storefront. Headless stores that disable the public feed, password-protected stores, and stores whose robots.txt disallows `products.json` are reported in `RUN_SUMMARY` and skipped.
- The feed doesn't include inventory quantities, only in-stock yes/no per variant.
- Currency is the store's default currency.
- Product data only: no customer or personal data is read or returned.

### 🔌 Use it via API, Python or integrations

Run it from the Apify Console, on a schedule, or from code with the Apify API, the Python or JavaScript `apify-client`, or MCP. Connect results to Google Sheets, Slack, Zapier, Make, n8n or a webhook from the **Integrations** tab.

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("lanternlane-data/shopify-store-products-scraper").call(run_input={"storeUrls": ["allbirds.com", "https://colourpop.com/collections/lips"], "outputLevel": "product"})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

### ❓ FAQ

**How do I know if a site is on Shopify?** Just add it. If it isn't (or the feed is disabled) the run tells you in `RUN_SUMMARY`.

**How do I monitor prices?** Use `outputLevel: variant`, keep `trackChanges` on, turn on `onlyChanges`, and schedule the Actor daily. Connect Slack, e-mail or a webhook integration to get alerts.

**Can I scrape only a collection?** Yes, paste the collection URL, e.g. `https://colourpop.com/collections/lips`.

**Something broke?** Open an issue on the Issues tab and we'll fix it fast.

### 🏮 More from Lantern Lane Data

**Jobs & hiring data** is our focus: job postings straight from employers' applicant tracking systems and official public feeds, in one consistent schema. More ATS platforms and hiring-signal tools are on the way.

- 💼 [ATS Jobs Scraper](https://apify.com/lanternlane-data/careers-page-jobs-aggregator): Every open job from 7 ATS platforms (Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable, Recruitee) in one schema, with new and closed job alerts.
- 🌍 [Remote Jobs Scraper](https://apify.com/lanternlane-data/remote-jobs-aggregator): Remote jobs from 7 boards via their official public feeds, deduplicated, with salary and location filters.

**Other tools**

- 🗺️ [Sitemap URL Extractor](https://apify.com/lanternlane-data/sitemap-url-extractor): Every URL from any website's XML sitemaps, with lastmod, hreflang and new-page alerts.
- 🔦 [AI Brand Visibility Tracker](https://apify.com/lanternlane-data/ai-brand-visibility-tracker): How often ChatGPT, Perplexity, Gemini and Claude mention, rank and cite your brand vs competitors.

***

Made by **Lantern Lane Data**. Not affiliated with Shopify Inc. or any store.

# Changelog

This Actor's version history is a separate document: https://apify.com/lanternlane-data/shopify-store-products-scraper/changelog.md

# Actor input Schema

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

Store domains or URLs, one per line: <code>allbirds.com</code>, <code>https://colourpop.com</code>. Add a collection URL (<code>https://colourpop.com/collections/lips</code>) to get only that collection.

## `outputLevel` (type: `string`):

Product: one record per product with a nested variants list. Variant: one flat record per variant (SKU), ideal for CSV/Sheets and price monitoring.

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

Keep products whose title, product type, vendor or tags contain one of these.

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

Exact product types to keep (case-insensitive), e.g. <code>Shoes</code>.

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

Exact vendor names to keep (case-insensitive).

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

Keep products (or variants) that are available to buy.

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

Keep products with a compare-at price above the current price.

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

In the store's currency.

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

In the store's currency.

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

<code>2026-10-01</code> or relative: <code>24 hours</code>, <code>7 days</code>.

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

Products read per store / collection (0 = all, up to 25,000).

## `maxResults` (type: `integer`):

Overall cap on output records (0 = no cap). Also caps your cost.

## `includeDescription` (type: `boolean`):

Plain-text product description.

## `trackChanges` (type: `boolean`):

Remember prices and stock between runs and set isNew, priceChanged, previousPrice and availabilityChanged.

## `onlyChanges` (type: `boolean`):

Output only items that are new or whose price or stock changed since the previous run (needs tracking on). Great for scheduled price alerts.

## `stateStoreName` (type: `string`):

Named key-value store that keeps the tracking snapshot. Use different names for separate monitors.

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

Requests go direct first. If a store rate-limits (HTTP 429), the Actor switches to a fresh proxy IP from this configuration. Apify Proxy (default) works well.

## Actor input object example

```json
{
  "storeUrls": [
    "allbirds.com",
    "https://colourpop.com/collections/lips"
  ],
  "outputLevel": "product",
  "onlyAvailable": false,
  "onlyOnSale": false,
  "maxProductsPerStore": 1000,
  "maxResults": 0,
  "includeDescription": true,
  "trackChanges": true,
  "onlyChanges": false,
  "stateStoreName": "shopify-products-tracker",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One record per product or variant.

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

Products read, records output and errors per 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 = {
    "storeUrls": [
        "allbirds.com",
        "https://colourpop.com/collections/lips"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("lanternlane-data/shopify-store-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 = {
    "storeUrls": [
        "allbirds.com",
        "https://colourpop.com/collections/lips",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("lanternlane-data/shopify-store-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 '{
  "storeUrls": [
    "allbirds.com",
    "https://colourpop.com/collections/lips"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call lanternlane-data/shopify-store-products-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lanternlane-data/shopify-store-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/HfPg9g3AWyz4T31Bd/builds/4XF3cqJY3b9zC8tZy/openapi.json
