# Product Price & Stock Change Monitor (JSON-LD) (`veteran_curio/product-price-stock-change-monitor-json-ld`) Actor

Track price and availability changes on public product pages with JSON-LD. Persist baselines between runs and export structured results. No browser, proxy, or LLM API key required. Free validation build.

- **URL**: https://apify.com/veteran_curio/product-price-stock-change-monitor-json-ld.md
- **Developed by:** [Tong Pu](https://apify.com/veteran_curio) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## 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 & Stock Change Monitor (JSON-LD)

Track price and availability changes on public product pages that include Product JSON-LD in their server HTML. Save an initial observation, run the same monitor again, and export the results or read the HTML report.

No CSS selectors, LLM API key, browser, or proxy setup is needed.

### Quick start

1. Add one or more public product URLs.
2. Choose a monitor name you will reuse, such as `demo-products`.
3. Run the Actor. The first successful check returns `BASELINE`.
4. Run again with the same URLs and monitor name. The result is `UNCHANGED` or `CHANGED` compared with the previous successful check.

Try this public demonstration page:

```json
{
  "urls": ["https://scrapeme.live/shop/Bulbasaur/"],
  "monitorId": "demo-products"
}
```

The demonstration page is operated by a third party and may change or become unavailable.

### Input

| Field | Description |
| --- | --- |
| `urls` | Required. Between 1 and 100 public HTTP(S) product URLs. Keep query parameters that select a product variant or currency. |
| `monitorId` | Optional name of up to 80 characters. Reuse it for comparisons across runs; use a new name to start a separate baseline. If omitted, the saved task ID is used when available, otherwise a default monitor is used. |

**Do not overlap runs that use the same monitor name.** Start the next run after the previous one finishes. To check periodically, save a task and configure an Apify schedule with enough time between runs. This Actor produces results and a report; it does not send notifications by itself.

### Results

Each processed URL produces one dataset row.

| Status | Meaning |
| --- | --- |
| `BASELINE` | First successful observation. There is no earlier value to compare, so `changed` is false. |
| `UNCHANGED` | The tracked fields match the previous successful observation. |
| `CHANGED` | One or more tracked fields changed. The `changes` array contains each field's old and new values. |
| `UNSUPPORTED` | The page did not provide one usable, unambiguous Product JSON-LD object. |
| `ERROR` | A request failed or was blocked by a network, robots, or safety limit. Read `diagnostics` for details. |

Successful rows include the product name, SKU, price or price range, currency, availability, source URLs, and check time when those values are available. Prices are decimal **strings**, such as `"63"`, to preserve the source value. Missing values are null; missing availability does not mean out of stock.

The tracked fields are name, product URL, SKU, exact price, minimum and maximum price, currency, and availability. Failed and unsupported checks keep the last successful baseline.

The Output tab provides:

- **Product checks:** the dataset, with an Overview view and a Details and diagnostics view. Export it to JSON, CSV, or other formats supported by Apify.
- **HTML report:** a readable summary and results table, stored as `REPORT` in the run's default key-value store.
- **Run summary (JSON):** requested and processed counts, a `stoppedEarly` flag, and counts by status, stored as `OUTPUT`.

Baselines are kept separately from each run's report and scoped to the account, Actor, and monitor.

### Supported pages and limits

The Actor reads the Product JSON-LD already present in the HTTP response. It supports ordinary Offer and AggregateOffer data, including unambiguous price ranges.

It does not run page JavaScript or log in. JavaScript-only product data, paywalls, CAPTCHA/anti-bot challenges, ambiguous product collections, and offers defined only by an unresolved `@id` reference are unsupported. It respects robots.txt and does not bypass access restrictions.

Checks are sequential. Each fetch has a 30-second overall timeout, a 2 MB response limit, and a limited number of redirects. UTF-8 HTML and uncompressed responses are supported. Start with a small list to confirm that your pages contain usable structured data.

Results reflect the merchant's structured markup. That markup can be stale or differ from a visible page or checkout price, so verify important changes against the source.

### Price

**This Actor has no rental, per-result, or pay-per-event fee.** Apify platform usage, including compute and storage, is billed separately under your account's plan. Available free credits may cover small runs. Check your Apify usage and limits when choosing a schedule or increasing the number of URLs.

# Actor input Schema

## `urls` (type: `array`):

1–100 public product pages whose server HTML contains Product JSON-LD. Login pages and JavaScript-only product data are unsupported.

## `monitorId` (type: `string`):

Reuse a name across runs to compare against earlier checks. If omitted, a saved task uses its task ID; other runs use an account-and-Actor-scoped default monitor. Do not overlap runs using the same monitor.

## Actor input object example

```json
{
  "urls": [
    "https://scrapeme.live/shop/Bulbasaur/"
  ]
}
```

# Actor output Schema

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

One dataset row per processed URL, including status, available product fields, changes, and diagnostics.

## `report` (type: `string`):

Readable results and summary for this run, saved as the REPORT record.

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

Requested and processed URL counts, stoppedEarly, and counts for BASELINE, CHANGED, UNCHANGED, UNSUPPORTED, and ERROR.

# 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 = {
    "urls": [
        "https://scrapeme.live/shop/Bulbasaur/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("veteran_curio/product-price-stock-change-monitor-json-ld").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 = { "urls": ["https://scrapeme.live/shop/Bulbasaur/"] }

# Run the Actor and wait for it to finish
run = client.actor("veteran_curio/product-price-stock-change-monitor-json-ld").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 '{
  "urls": [
    "https://scrapeme.live/shop/Bulbasaur/"
  ]
}' |
apify call veteran_curio/product-price-stock-change-monitor-json-ld --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,veteran_curio/product-price-stock-change-monitor-json-ld"
        }
    }
}
```

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/qJO1aLdzBN522Vnfo/builds/nB2T6gYFmgoTsH2ac/openapi.json
