# Product Feed Price & Stock Checker (`exceptional_nugget/product-feed-price-checker`) Actor

Compare product feed prices, currencies and stock with SKU-matched JSON-LD offers. Flag ambiguous variants and export a client report.

- **URL**: https://apify.com/exceptional\_nugget/product-feed-price-checker.md
- **Developed by:** [LibriHouse](https://apify.com/exceptional_nugget) (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 $4.00 / 1,000 product checkeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Product Feed Price & Stock Checker

Compare your submitted product prices, currencies and optional stock status with JSON-LD Product offers on their public landing pages. Match an exact SKU when supplied; flag ambiguous variants instead of guessing. Get an actionable dataset and printable client report with no proxy, AI or paid API key.

### Quick start

```json
{
  "products": [
    {
      "id": "demo-hoodie",
      "url": "https://www.scrapingcourse.com/ecommerce/product/abominable-hoodie/",
      "sku": "MH09",
      "price": "69.00",
      "currency": "USD"
    }
  ],
  "maxRedirects": 3,
  "timeoutSecs": 15,
  "delayMillis": 250
}
```

This example uses a public scraping demonstration shop. Its price can change; a mismatch is a valid result. Replace the product with your catalog data. Convert selected rows from your feed into the JSON array; this release does not download XML/CSV feeds.

| Input | Meaning |
|---|---|
| `products` | 1–1000 objects, each requiring `url`, `price` and `currency`. |
| `id` | Optional nonempty reference string, maximum 200 characters; defaults to row number. |
| `sku` | Optional exact case-sensitive SKU, maximum 200 characters. Strongly recommended for variant pages. SKU matching uses Offer.sku when present, otherwise Product.sku. |
| `price` | Nonnegative decimal string or number, up to 12 integer and 6 fractional digits. Strings preserve decimal precision. No currency symbols, separators or exponent notation. Supply the currently advertised price, including sale price where appropriate. |
| `currency` | Required three-letter uppercase code, e.g. USD. No currency conversion is performed. |
| `availability` | Optional: `in_stock`, `out_of_stock`, `preorder` or `backorder`. Omit to skip stock comparison. |
| `maxRedirects` | 0–5 per page, default 3. |
| `timeoutSecs` | 2–30 seconds per request including DNS, default 15. |
| `delayMillis` | 100–5000 ms between requests, default 250. |

### How matching works

The Actor parses `application/ld+json` scripts, finds Product nodes including nested ProductGroup variants, and resolves local `@id` references to Offer nodes. It reads exact `Offer.price`, `priceCurrency` and `availability` evidence.

When a SKU is supplied, only matching offers are candidates. Without a SKU, pages containing multiple Product nodes are marked ambiguous. Multiple offers with different price/currency/stock values remain unknown—even if one price equals your expected price. Repeated offers with identical values are accepted. AggregateOffer ranges, unsupported offer types and malformed or truncated structured data cannot yield a confident match.

Prices compare exactly to six decimal places without binary floating-point rounding. `69`, `69.0` and `69.00` are equivalent. No tolerance or regional currency conversion is guessed. Recognized stock values are Schema.org InStock, OutOfStock, SoldOut, PreOrder and BackOrder. Other stock vocabulary remains unknown.

### Results

- `match`: all requested comparisons were established and equal.
- `mismatch`: at least one established price, currency or stock comparison differs.
- `unknown`: the selected offer or required evidence could not be established reliably.

Unknown is not a product defect or a Merchant Center disapproval. A mismatch can coexist with an unavailable optional comparison; inspect the individual nullable `priceMatches`, `currencyMatches`, `availabilityMatches` fields and issue codes. Each row includes expected/observed values, HTTP status, redirect chain, SKU, timestamp and up to five candidate evidence records. Evidence names/URLs are bounded for report size; `candidateCount` gives the full count.

Export the dataset as JSON, CSV or Excel in Apify. **Printable client report** opens `REPORT` HTML; **Audit summary** opens `SUMMARY` JSON. Download the HTML and print it to PDF if needed. `SUMMARY.complete` identifies whether all supplied records were processed. Use `itemIndex` to join results to your original rows; duplicate rows are checked and billed separately.

Use Apify schedules to repeat a saved input after catalog updates. This release does not connect to Merchant Center, change feeds, retain cross-run baselines, or send alerts automatically.

### Pricing

Launch price: **$4 per 1,000 completed product checks** (`product-checked`, $0.004 each), plus the Apify start event ($0.00005 at the default 256 MB) and platform usage. Start-event count increases above 1 GB. Confirm the current Pricing tab before running. For 100 checks, product events total $0.40 plus the start event and platform usage. Reports and mismatch lists have no extra event charge.

Completed HTTP observations are charged even when evidence is missing, ambiguous, blocked (403/429), non-HTML, matched or mismatched. Transport/DNS/TLS/timeout/security failures with a populated `error` field have no custom product fee. Start fee and platform usage still apply. The Actor stops before work that cannot fit its event budget. Do not add automatic dataset-item billing alongside `product-checked`.

### Limitations and privacy

This is a **static structured-data comparison**, not a guarantee about visible page prices, checkout totals, variant selection, ad approval or policy compliance. It does not execute JavaScript, inspect Microdata/RDFa/visible-price selectors, resolve remote JSON-LD contexts, evaluate priceSpecification or AggregateOffer ranges, apply discounts/coupons, calculate tax/shipping, or emulate a buyer's location. Supply the correct expected SKU and regional URL. Structured data itself can be stale; manually review flagged products.

HTML is capped at 2 MB, JSON-LD at 100 scripts/20,000 nodes/30 nesting levels. Only UTF-8/ASCII, identity-encoded HTML is parsed. Public standard-port HTTP(S) URLs only, no login or embedded credentials. All DNS answers are checked; the selected public IP is pinned and redirects revalidated. Private/reserved networks and unsafe protocols are rejected. No automatic retries of blocked pages.

Results stay in your Apify storage with your account's access and retention settings; no external database or analytics is used. Do not submit URLs containing secrets or personal query parameters. Limited permissions are sufficient. Interrupted reports may lag the dataset by up to 24 records; the dataset is authoritative. Normal completion, graceful abort and budget stops refresh the report. Dataset writes and charging are not a cross-service transaction; inspect interrupted paid runs before resurrection.

### Support

Include a run ID, sanitized product input, expected behavior and issue code in an Actor issue. Never share your API token. Do not treat an unknown result as proof of a price mismatch.

# Actor input Schema

## `products` (type: `array`):

1–1000 {url, price, currency, id?, sku?, availability?} records. Exact SKU recommended for variants. Price decimal; availability in\_stock/out\_of\_stock/preorder/backorder. JSON-LD offers only.

## `timeoutSecs` (type: `integer`):

Per-request deadline including DNS lookup. Range 2–30 seconds.

## `maxRedirects` (type: `integer`):

Maximum redirects followed for each supplied source page. Range 0–5.

## `delayMillis` (type: `integer`):

Delay between page requests and redirect hops. Range 100–5000 milliseconds.

## Actor input object example

```json
{
  "products": [
    {
      "id": "demo-hoodie",
      "url": "https://www.scrapingcourse.com/ecommerce/product/abominable-hoodie/",
      "sku": "MH09",
      "price": "69.00",
      "currency": "USD"
    }
  ],
  "timeoutSecs": 15,
  "maxRedirects": 3,
  "delayMillis": 250
}
```

# Actor output Schema

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

No description

## `report` (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 = {
    "products": [
        {
            "id": "demo-hoodie",
            "url": "https://www.scrapingcourse.com/ecommerce/product/abominable-hoodie/",
            "sku": "MH09",
            "price": "69.00",
            "currency": "USD"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("exceptional_nugget/product-feed-price-checker").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 = { "products": [{
            "id": "demo-hoodie",
            "url": "https://www.scrapingcourse.com/ecommerce/product/abominable-hoodie/",
            "sku": "MH09",
            "price": "69.00",
            "currency": "USD",
        }] }

# Run the Actor and wait for it to finish
run = client.actor("exceptional_nugget/product-feed-price-checker").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 '{
  "products": [
    {
      "id": "demo-hoodie",
      "url": "https://www.scrapingcourse.com/ecommerce/product/abominable-hoodie/",
      "sku": "MH09",
      "price": "69.00",
      "currency": "USD"
    }
  ]
}' |
apify call exceptional_nugget/product-feed-price-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,exceptional_nugget/product-feed-price-checker"
        }
    }
}
```

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/AICTgNwOz33dNWexD/builds/njf5gRNthSfvVTGdq/openapi.json
