# Product Price Tracker - Stock & Variants Monitor (`invincible_brookbed/ecommerce-price-monitor`) Actor

Monitor product price, currency, availability and variants from any product URL. Parses JSON-LD and Open Graph - no store login or CSS selectors. Perfect for competitive pricing and restock alerts. MCP-ready.

- **URL**: https://apify.com/invincible_brookbed/ecommerce-price-monitor.md
- **Developed by:** [Виталий Белогуров](https://apify.com/invincible_brookbed) (community)
- **Categories:** E-commerce, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 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.

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

## Product Price Tracker — Stock & Variants Monitor

**Product price tracker API for competitor monitoring.** Track price, currency, availability and variants from any product page URL — no CSS selectors, no per-site scrapers, no logins. Schedule it, diff the results, and know when prices or stock change (~**$20 per 1,000 products**).

### Why users pick this Actor

- Clear pay-per-event pricing — you only pay for successful results (~$0.02/product)
- Structured JSON ready for CRM, sheets, Zapier/Make/n8n
- Works with AI agents via [Apify MCP](https://mcp.apify.com/)
- Honest limitations documented — no fake data

E-commerce Price Monitor reads the structured data that online shops already publish for Google: **schema.org JSON-LD `Product`** markup, with Open Graph / `product:*` meta tags and microdata as fallbacks. That means one Actor works across thousands of shops (Shopify, WooCommerce, Magento, BigCommerce and custom stores) as long as the product page exposes standard markup.

### What does it do?

- Fetches each product URL over plain HTTP (fast and cheap — no browser).
- Extracts **name, SKU, brand, image, price, currency and availability**.
- Collects **variants** (sizes, colours, offers) from `ProductGroup.hasVariant` or multiple offers, capped by `maxVariants`.
- Normalises availability to one vocabulary: `in_stock`, `out_of_stock`, `limited_stock`, `preorder`, `backorder`, `discontinued`, `online_only`, `in_store_only`, `unknown`.
- Optionally converts prices to a **target currency** using daily reference exchange rates.
- Tells you which source was used (`json-ld`, `json-ld+meta`, `microdata`, `meta`) so you can judge data quality.

### Why use this Actor?

| | Custom scraper per shop | Browser-based scraper | **E-commerce Price Monitor** |
|---|---|---|---|
| Time to add a new shop | Hours of selector work | Hours | **Zero — paste the URL** |
| Breaks when the theme changes | Often | Often | **Rarely (uses standard markup)** |
| Run cost | Developer time | High (browser compute) | **Low flat price per product** |
| Variants & stock | Per-site logic | Per-site logic | **Built in** |
| Multi-currency comparison | DIY | DIY | **Built-in `targetCurrency`** |
| Failed pages charged | n/a | Compute spent anyway | **No** |

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `productUrls` | array | — (required) | Direct product page URLs (not category/search pages). |
| `targetCurrency` | string | none | ISO 4217 code (e.g. `USD`, `EUR`). Adds `priceConverted` to each record. |
| `maxVariants` | integer | `20` | Max variants stored per product (0–200). |
| `proxyConfiguration` | object | Residential | Optional Residential Apify Proxy (prefilled). Turn off if the shop works without it. No captcha needed. |

```json
{
    "productUrls": [{ "url": "https://www.allbirds.com/products/mens-tree-runners" }],
    "targetCurrency": "EUR",
    "maxVariants": 20,
    "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

### Output

One record per URL:

```json
{
    "url": "https://www.allbirds.com/products/mens-tree-runners",
    "finalUrl": null,
    "name": "Men's Tree Runner",
    "sku": "MENS_TREE_RUNNERS",
    "brand": "Allbirds",
    "price": { "amount": 100, "currency": "USD" },
    "priceConverted": { "amount": 92.1, "currency": "EUR", "rate": 0.921, "rateDate": "2026-10-09" },
    "availability": "in_stock",
    "availabilityRaw": "https://schema.org/InStock",
    "variants": [
        {
            "name": "Men's Tree Runner - Jet Black",
            "sku": "TR3MJBW080",
            "price": { "amount": 100, "currency": "USD" },
            "availability": "in_stock",
            "url": "https://www.allbirds.com/products/mens-tree-runners-jet-black",
            "imageUrl": "https://www.allbirds.com/cdn/shop/files/example.png"
        }
    ],
    "imageUrl": "https://www.allbirds.com/cdn/shop/files/example.png",
    "source": "json-ld",
    "error": null,
    "scrapedAt": "2026-10-11T09:30:12.481Z"
}
```

`price` is the **lowest in-stock price** found (or the lowest overall if everything is sold out). Pages with no usable data return a record with an `error` field and are not charged. End-of-run statistics (checked, in stock, out of stock, failures, charged events) are stored under `STATS`.

### Pricing

**Pay-per-event** pricing:

| Event | Price | When it is charged |
|---|---|---|
| `product-checked` | **$0.02** (about $20 per 1,000 products) | A product with a name plus a price or availability was extracted |

- Failed requests, blocked pages and pages without product data are **free**.
- Platform compute is included in the event price.
- Use the Console's maximum cost per run to hard-cap spending.

### Use cases

- **Competitor price tracking:** schedule daily runs and diff prices across rivals.
- **MAP / pricing compliance:** verify that resellers stick to agreed prices.
- **Stock alerts & restock monitoring:** watch availability of limited drops.
- **Dropshipping & arbitrage:** compare supplier prices in a single currency.
- **Market research & datasets:** build product catalogues with brand, SKU and variants.

### FAQ

**Which shops are supported?**
Any shop whose product pages include schema.org `Product` JSON-LD, Open Graph product tags or microdata. Most modern platforms do. There is no site-specific code.

**Why did I get "No product data found"?**
The URL may be a category page, the shop may inject product data with JavaScript only, or it may be showing a bot-check page. Try a residential proxy, or confirm the data appears in the page source.

**Can it log in to see member prices?**
No. It reads publicly visible pages only.

**How are currencies converted?**
With daily reference rates from Frankfurter (ECB) or open.er-api.com. Your original `price` is never modified. If rates are unavailable, `priceConverted` is `null`.

**How do I monitor changes over time?**
Schedule the Actor and compare datasets, or push results to a webhook, Google Sheets or your database using Apify integrations.

**Is the price tax-inclusive?**
It's whatever the shop publishes in its markup. Some shops publish ex-tax prices, others include VAT.

### MCP — use it from AI agents

Ready for the Model Context Protocol, so Claude, Cursor and other agents can call it as a tool:

`https://mcp.apify.com/?tools=fetch-actor-details,invincible_brookbed/ecommerce-price-monitor`

Try: *"Check the price and stock of these five product pages and convert everything to EUR."*

### Limitations

- Needs standard structured data; JavaScript-only price widgets are not executed.
- Prices shown only after choosing a variant may reflect the default or lowest offer.
- Shops with strict anti-bot protection may block requests even with proxies.
- Variant details depend on what the shop exposes in its markup; some publish none.

# Actor input Schema

## `productUrls` (type: `array`):

Direct links to individual product pages (not category or search pages).

## `targetCurrency` (type: `string`):

Optional ISO 4217 code (e.g. USD, EUR, GBP). When set, each record also gets a priceConverted object using daily reference exchange rates. The original price is always kept untouched.

## `maxVariants` (type: `integer`):

Cap on variants/offers stored per product record.

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

Optional. Prefills Residential Apify Proxy — useful for shops that block datacenter IPs. Turn off if the store works without it. Captcha solving is not required.

## Actor input object example

```json
{
  "productUrls": [
    "https://www.allbirds.com/products/mens-tree-runners"
  ],
  "maxVariants": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset with price, stock and variant data.

## `stats` (type: `string`):

End-of-run statistics (products checked, failures, charged events).

# 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 = {
    "productUrls": [
        "https://www.allbirds.com/products/mens-tree-runners"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("invincible_brookbed/ecommerce-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 = {
    "productUrls": ["https://www.allbirds.com/products/mens-tree-runners"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("invincible_brookbed/ecommerce-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 '{
  "productUrls": [
    "https://www.allbirds.com/products/mens-tree-runners"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call invincible_brookbed/ecommerce-price-monitor --silent --output-dataset

```

## MCP server setup

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