# Shopify Store Scraper & Price Monitor (`aimindteams/shopify-catalog-price-monitor`) Actor

Scrape any Shopify store's products, variants, prices, discounts and stock, and get price drops, restocks, sell-outs, new and removed products on every scheduled run. No API key, no login.

- **URL**: https://apify.com/aimindteams/shopify-catalog-price-monitor.md
- **Developed by:** [AIMindTeams](https://apify.com/aimindteams) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 product scrapeds

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 Store Scraper & Price Monitor

**Scrape any Shopify store's full catalog, then watch it for changes.** Add store domains and get every product with:

- **Prices and price ranges**, compare-at ("was") prices, **discount %** and on-sale flags
- **Stock status** per variant (size, color ...), SKUs, weights and options
- **Vendor, product type, tags**, images, handles and links, plus optional descriptions
- **Store details**: name, currency and country

Turn on **change tracking** for scheduled monitoring and each run returns only what changed since the last one:

**price drops · price increases · back in stock · sold out · new products · removed products**

No API key, no login, no browser. Press **Start** to scrape three sample stores (Allbirds, Death Wish Coffee and Tentree) in seconds.

***

### Why this Actor exists

Every Shopify store publishes its catalog through a public storefront feed. Most Shopify scrapers dump that feed once. This Actor turns it into a **price and stock monitor**: it remembers each store's catalog between runs and tells you exactly what moved.

| | Typical Shopify scraper | **Shopify Store Scraper & Price Monitor** |
|---|---|---|
| Products, variants, prices | Yes | Yes |
| Discount % and on-sale flags | Rarely | **Yes** |
| Stock per variant | Sometimes | **Yes** |
| Collections, vendor, type, keyword and price filters | Few | **All** |
| Product-level or variant-level rows | One fixed shape | **Your choice** |
| Price drops, restocks, sell-outs, new and removed products | No | **Yes, between runs** |
| Store catalog summary | No | **Yes** |

***

### How it works

1. **Check** each store's public product feed and read its name, currency and country.
2. **Page through** the catalog (or only the collections you list), 250 products per request, politely.
3. **Normalize** prices to numbers, compute discounts and stock, and apply your filters.
4. **Compare** with the previous run's snapshot when change tracking is on.
5. **Deliver** one row per product (or per variant) and a catalog summary per store.

***

### Quick start

**One-off catalog export**

```json
{
    "stores": ["allbirds.com", "example-store.com"],
    "maxProductsPerStore": 5000
}
```

**Daily price-drop and restock monitor** (run on a schedule)

```json
{
    "stores": ["competitor-one.com", "competitor-two.com"],
    "trackChanges": true,
    "onlyChanges": true,
    "maxProductsPerStore": 25000
}
```

The first monitored run saves a **baseline** and returns the catalog. Every later run returns only changed products.

**Deals finder**

```json
{
    "stores": ["allbirds.com"],
    "onSaleOnly": true,
    "onlyAvailable": true,
    "outputLevel": "variant"
}
```

***

### Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `stores` | array | 3 samples | Store domains or URLs (custom domains or .myshopify.com). |
| `collections` | array | none | Only these collections (handles or collection URLs). |
| `keywords` | array | none | Match title, tags, vendor or product type. |
| `vendors` | array | none | Match vendor (brand). |
| `productTypes` | array | none | Match product type. |
| `onlyAvailable` | boolean | false | In-stock products or variants only. |
| `onSaleOnly` | boolean | false | Discounted products or variants only. |
| `minPrice` / `maxPrice` | integer | none | Price range in the store's currency. |
| `maxProductsPerStore` | integer | 1000 | Cap per store after filters (Shopify serves up to 25,000). |
| `outputLevel` | `product` or `variant` | product | One row per product or per variant. |
| `includeDescription` | boolean | false | Add the description as clean text. |
| `trackChanges` | boolean | false | Compare with the previous run and label changes. |
| `onlyChanges` | boolean | true | With tracking on, deliver only changed products after the baseline. |
| `maxConcurrency` | integer | 3 | Stores processed in parallel. |

***

### Output

**Product row** (shortened):

```json
{
    "store": "www.allbirds.com",
    "store_name": "Allbirds",
    "currency": "USD",
    "product_id": "7340901859408",
    "title": "Women's Allbirds Flip Flop - Dusty Pink",
    "handle": "womens-allbirds-flip-flop-dusty-pink",
    "url": "https://www.allbirds.com/products/womens-allbirds-flip-flop-dusty-pink",
    "vendor": "Allbirds",
    "product_type": "Shoes",
    "tags": ["womens"],
    "price_min": 25.0,
    "price_max": 25.0,
    "compare_at_price_max": 50.0,
    "on_sale": true,
    "max_discount_pct": 50.0,
    "available": true,
    "variants_count": 7,
    "available_variants_count": 3,
    "options": [{ "name": "Size", "values": ["5", "6", "7", "8", "9", "10", "11"] }],
    "variants": [
        { "variant_id": "42146889039952", "title": "5", "sku": "A12513W050", "options": ["5"], "price": 25.0, "compare_at_price": 50.0, "on_sale": true, "discount_pct": 50.0, "available": false, "grams": 455 }
    ],
    "image": "https://cdn.shopify.com/s/files/1/1104/4168/files/A12513_Flip-Flop.png",
    "change_type": "price_drop",
    "changes": [
        { "type": "price_drop", "variant_id": "42146889039952", "variant_title": "5", "old_price": 30.0, "new_price": 25.0, "change_pct": -16.7 }
    ],
    "scraped_at": "2026-10-17T19:00:00Z"
}
```

**Change types**: `baseline` (first monitored run), `new_product`, `price_drop`, `back_in_stock`, `price_increase`, `sold_out`, `new_variant`, `removed`, `unchanged`, or `untracked` when tracking is off.

**Catalog summary** (`OUTPUT` record), one row per store: name, currency, country, products scanned, whether the whole catalog was read, in-stock and on-sale shares, price min, median and max, top vendors, top product types and change counts.

***

### Pricing (Pay-Per-Event)

| Event | When | Price |
|---|---|---|
| `product-scraped` | One product row (or one variant row) is delivered | See the **Pricing** tab |

- You only pay for delivered rows. Store checks, pages and comparisons are included.
- With change tracking and **Deliver only changed products**, unchanged products are free after the baseline run.
- Your run's maximum charge is respected: the Actor checks the remaining budget **before** each row.

***

### Use cases

- **Competitor price monitoring**: get a daily list of price drops and promotions at competing stores.
- **Restock alerts**: know when sold-out products come back.
- **Catalog and assortment research**: vendors, product types, price bands and discount depth for any brand.
- **Dropshipping and arbitrage**: find discounted, in-stock items across many stores.
- **Market research**: track how often brands launch new products or retire old ones.

Connect the dataset to Slack, email, Google Sheets or Zapier with Apify integrations to turn changes into alerts.

***

### Use it from AI agents (MCP)

**Hosted Apify MCP server** (Claude, ChatGPT, Cursor, VS Code and any client that supports remote MCP):

```
https://mcp.apify.com?tools=AIMindTeams/shopify-catalog-price-monitor
```

**Local stdio server** (for example, Claude Desktop `claude_desktop_config.json`):

```json
{
    "mcpServers": {
        "shopify-monitor": {
            "command": "npx",
            "args": ["-y", "@apify/actors-mcp-server", "--tools", "AIMindTeams/shopify-catalog-price-monitor"],
            "env": { "APIFY_TOKEN": "YOUR_APIFY_TOKEN" }
        }
    }
}
```

Example prompts:

- "Which products on allbirds.com are discounted more than 30% and in stock in size 10?"
- "Compare the price range and top product types of these three coffee brands' stores."
- "Set up a daily check and tell me what dropped in price at my competitors' stores."

***

### Use it from code

**Python** (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("AIMindTeams/shopify-catalog-price-monitor").call(
    run_input={"stores": ["allbirds.com"], "trackChanges": True}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["change_type"], item["title"], item["price_min"], item["url"])
```

**cURL** (run and get the items in one call):

```bash
curl -X POST "https://api.apify.com/v2/acts/AIMindTeams~shopify-catalog-price-monitor/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"stores": ["deathwishcoffee.com"], "onSaleOnly": true}'
```

***

### FAQ

**Does it work with every Shopify store?**
It works with stores that keep Shopify's public product feed enabled, which is the default and covers the vast majority. Stores that disable it or are password protected are listed in the summary as unavailable and are not charged.

**What currency are prices in?**
The store's base currency, shown in the `currency` field.

**How does change tracking work?**
Each store's catalog (product IDs, variant prices and stock) is saved after every monitored run in a Key-Value Store named `SHOPIFY-CATALOG-SNAPSHOTS`. The next run compares against it. Each combination of store and collection filter keeps its own snapshot.

**Are removed products detected reliably?**
Yes, but only when the whole catalog (or collection) was read in that run. If a run stops early, nothing is reported as removed.

**Is this legal?**
The Actor reads the public catalog feed that Shopify stores publish for their storefronts. Use the data in line with the laws and terms that apply to you.

***

### More from AIMindTeams

- [Website Contact & Tech Stack Enricher](https://apify.com/aimindteams/website-contact-tech-enricher): emails, phones, social profiles, tech stack and email provider for any list of company websites.
- [Career Site Jobs Scraper](https://apify.com/aimindteams/career-site-jobs-scraper): every open job from Greenhouse, Lever, Ashby, Workday and other career sites, with salaries and hiring signals.
- [SAM.gov & SBIR Federal RFP + Attachment Deep-Parser](https://apify.com/aimindteams/govcon-rfp-deep-parser): federal opportunities with their attachments parsed.

***

### Changelog

- **1.0**: First release. Product- and variant-level output, collections and filters, discounts and stock, store summaries, and change tracking for price drops, price increases, restocks, sell-outs, new and removed products.

# Actor input Schema

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

Store domains or URLs, one per line, for example allbirds.com or https://www.example-store.com. Custom domains and .myshopify.com addresses both work.

## `collections` (type: `array`):

Only scrape these collections: handles (sale, mens-shoes) or collection URLs (https://store.com/collections/sale). Leave empty for the whole catalog.

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

Optional. Keep products whose title, tags, vendor or product type contains any of these.

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

Optional. Keep products from these vendors (partial, case-insensitive match).

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

Optional. Keep products whose product type contains any of these, for example Shoes or Coffee.

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

Keep products (or variants) that can be bought right now.

## `onSaleOnly` (type: `boolean`):

Keep products (or variants) with a compare-at price higher than the current price.

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

Optional, in the store's currency.

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

Optional, in the store's currency.

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

Upper limit of products delivered per store after filters. Shopify serves up to 25,000 products per store or collection.

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

One row per product (variants nested inside) or one row per variant (size, color ...). Each row is one billable item.

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

Add the product description as clean text (up to 10,000 characters).

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

Turn this on for scheduled monitoring. The first run saves a baseline snapshot of each store (in the SHOPIFY-CATALOG-SNAPSHOTS Key-Value Store) and returns the matching catalog. Later runs compare against it and label price drops, price increases, restocks, sell-outs, new and removed products.

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

With change tracking on, skip unchanged products after the baseline run, so you only receive (and pay for) what changed.

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

Pages of each store are read one after another to stay polite; several stores can run in parallel.

## Actor input object example

```json
{
  "stores": [
    "allbirds.com",
    "deathwishcoffee.com",
    "tentree.com"
  ],
  "onlyAvailable": false,
  "onSaleOnly": false,
  "maxProductsPerStore": 50,
  "outputLevel": "product",
  "includeDescription": false,
  "trackChanges": false,
  "onlyChanges": true,
  "maxConcurrency": 3
}
```

# Actor output Schema

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

Every product with vendor, type, tags, price range, discount, stock, variants, options, images and, with change tracking, the detected changes.

## `overview` (type: `string`):

Flattened one-row-per-product view. Append \&format=csv or \&format=xlsx for spreadsheets.

## `storeSummary` (type: `string`):

Store name, currency, products scanned, in-stock and on-sale shares, price range and median, top vendors and product types, and change counts.

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

// Run the Actor and wait for it to finish
const run = await client.actor("aimindteams/shopify-catalog-price-monitor").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": [
        "allbirds.com",
        "deathwishcoffee.com",
        "tentree.com",
    ],
    "maxProductsPerStore": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("aimindteams/shopify-catalog-price-monitor").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": [
    "allbirds.com",
    "deathwishcoffee.com",
    "tentree.com"
  ],
  "maxProductsPerStore": 50
}' |
apify call aimindteams/shopify-catalog-price-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,aimindteams/shopify-catalog-price-monitor"
        }
    }
}
```

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/RdWMewL4Ssxt46RE7/builds/m5IvTDRwQUTcX8hu2/openapi.json
