# Amazon Buy Box & Price Monitor 📦 (with seller ID check) (`tagadanar/amazon-product-monitor`) Actor

Watch the Buy Box on any Amazon listing: live price, who is winning it, who fulfils it and whether stock moved, with a change record whenever one shifts. On EU marketplaces it also reads the seller identity Amazon must publish and checks it against the official VAT and company registers.

- **URL**: https://apify.com/tagadanar/amazon-product-monitor.md
- **Developed by:** [Tagada Data](https://apify.com/tagadanar) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.45 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Amazon Buy Box & Price Monitor (with seller identity check)

Know the moment the Buy Box moves. Give this actor a list of ASINs and it comes
back with the live Buy Box price, who is winning it, who fulfils it, whether the
listing is in stock, plus rating, review count and Best Sellers Rank. Turn on
change tracking, schedule it daily, and every later run tells you what actually
moved: a price cut, a new seller taking the Buy Box, a listing going out of
stock.

The second half is the part other Amazon scrapers do not do. On the European
marketplaces, EU law obliges Amazon to publish the legal identity of every
business seller on its storefront: business name, registered address, VAT
number, trade register number. This actor reads that block and checks it against
an official register (the EU VAT system, the French company register, or
Companies House for the UK), then tells you whether the two agree. That is how
you find out that the "German" seller holding the Buy Box on your listing is a
company registered in Shenzhen.

No API key. No login. No browser. Plain HTTP, so a hundred ASINs is a couple of
minutes.

### What it costs

| Event | Price, all-in |
| --- | --- |
| Each product (ASIN) returned | $3.50 per 1,000 |
| Each search result row | $1.20 per 1,000 |
| Each seller identity verified | $12.00 per 1,000 |
| Each change found, in change-tracking mode | $0.80 per 1,000 |
| Run start | $0.001 |

Platform usage (compute, proxies) is included — this actor reads Amazon over
plain HTTP with no proxy, and that saving is already in the price. You are
charged for rows delivered: a product that cannot be read, a marketplace that
blocks mid-run, and a run that finds no changes are not billed for those rows,
and the run says so in its status message.

### What you get

Every run writes one flat dataset. Records are told apart by `recordType`.

#### `product` — one per watched ASIN

| field | what it is |
| --- | --- |
| `asin`, `marketplace`, `url`, `title`, `brand` | identity of the listing |
| `price`, `currency`, `priceText` | the live Buy Box price |
| `listPrice` | the struck-through was-price, when Amazon shows one |
| `buyBoxSeller` | `{ name, id, isAmazon, fulfilledBy }`: who is selling and who ships |
| `availability`, `inStock` | Amazon's own stock wording, plus a boolean |
| `rating`, `reviewCount` | star rating and how many ratings (a count, not review text) |
| `bsr`, `bsrCategory` | Best Sellers Rank and the category it ranks in |
| `imageCount` | how many images the listing carries |
| `parseStatus` | `full`, `no-buy-box` when Amazon withheld the offer, or `degraded-render` when Amazon served its cached price-less page |
| `sellerVerification` | a short summary of the seller check, when it is on |
| `capturedAt` | ISO timestamp |

#### `search` — one per search result, when you pass keywords

`asin`, `title`, `price`, `currency`, `listPrice`, `rating`, `reviewCount`,
`position`, `page`, `sponsored`, `searchQuery`, `url`. Sponsored slots are
flagged, not hidden, so you can measure organic rank separately from paid.

#### `seller` — one per verified seller

One record per seller, whether it came from a Buy Box or from an ID you gave:
`sellerId`, `storeName`, `businessName`, `businessType`, `registrationId`,
`vatId`, `address`, `countryCode`, `phone`, `email`, `sellerRating`,
`positiveFeedbackPct`, `feedbackCount`, `disclosurePublished`, `sellerUrl`, and
`registryMatch`:

```json
{
  "source": "VIES",
  "status": "verified",
  "matchedName": "SA DANONE",
  "matchedAddress": "59 RUE LA FAYETTE, 75009 PARIS",
  "registryId": null,
  "registryIdType": null,
  "confidence": 96,
  "matchType": "exact-without-legal-form",
  "checkedVat": "FR27552032534",
  "note": null
}
```

`status` is deliberately blunt about the difference between checked-and-good,
checked-and-bad, and could-not-check:

| status | meaning |
| --- | --- |
| `verified` | the VAT number or register entry is real and the name matches what Amazon publishes |
| `name-mismatch` | the number is real, the name attached to it is not the one on the storefront |
| `vat-not-registered` | the VAT number Amazon shows is not a live number |
| `vat-valid-name-withheld` | the number checks out but the country does not publish the trader name (this is normal for Germany) |
| `registered-but-ceased` | matched a company that the register says has stopped trading |
| `no-disclosure-published` | the marketplace published no identity block for this storefront |
| `registry-unreachable` | the official service was down; nothing was concluded |

#### `change` — one per product that moved, in change-tracking mode

`field` (`price`, `buyBoxSeller` or `availability`), `previous`, `current`,
`delta`, `percentChange`, `changedFields`, `changes` (every field that moved),
`previousSeenAt`, `detectedAt`.

### Who this is for

**Brands and sellers defending a listing.** You care about one thing: is anyone
else in your Buy Box, and at what price. Put your ASINs in, turn on change
tracking and "only changed products", schedule it hourly or daily, and the run
returns nothing on a quiet day and a short list on a bad one.

**Repricing and margin work.** Price, list price, Buy Box holder and fulfilment
channel per ASIN, with the change history built from your own runs rather than a
third-party price index.

**Procurement and compliance teams.** Before you buy from a marketplace seller
at volume, you want to know who they legally are, where they are, and whether
their VAT number is real. The `seller` records answer that from official
sources, with a confidence score you can show your auditor.

**Category and SEO research.** Search keywords give you the ranked shelf with
sponsored slots flagged, so you can see who is buying position and who is
earning it.

### Marketplaces

`amazon.com`, `amazon.co.uk`, `amazon.de`, `amazon.fr`, `amazon.it`,
`amazon.es`. Pick one with the Marketplace field for your ASINs and keywords.
Full product URLs keep their own marketplace, so you can watch a product on
amazon.com and amazon.de in the same run.

Seller identity verification only runs on the European marketplaces, because
the disclosure it reads is an EU obligation. On amazon.com there is no such
block to read, so the option is quietly skipped there rather than returning
half an answer.

There are two ways to reach it. Turn on "Verify who the seller really is" and
every third-party seller holding the Buy Box on your products gets checked. Or
name the sellers yourself in "Sellers to verify by ID", which opens each
storefront directly and never touches a product page at all.

The second one exists for a reason worth knowing. Amazon decides what to show
based on the region it thinks the request came from, and a run that leaves from
outside Europe often gets the international "global store" offer on a European
listing, where Amazon itself is the seller. When Amazon holds the Buy Box there
is no third-party identity to verify, so no `seller` record is produced and
nothing is billed for it. Naming seller IDs sidesteps that entirely: the
storefront page is served the same way wherever the run leaves from.

### Input examples

Watch three ASINs on amazon.com and see the current state:

```json
{
  "asins": ["B00PGB7OKM", "B0BXNR9DB6", "B0FB9BR23C"],
  "marketplace": "com"
}
```

Daily Buy Box watch that only reports movement (schedule this one):

```json
{
  "asins": ["B00PGB7OKM", "B0BXNR9DB6"],
  "marketplace": "com",
  "monitorMode": true,
  "onlyChanges": true
}
```

Check who is really behind two sellers you already know about:

```json
{
  "sellerIds": ["de:A3GX1RCD4Z9H04", "de:AB4RD1JXHRRE1"]
}
```

Check who is really behind the sellers on a German listing:

```json
{
  "productUrls": ["https://www.amazon.de/dp/B0DK955V6Z"],
  "verifySeller": true
}
```

Track a keyword shelf and the products on it in one run:

```json
{
  "searchQueries": ["wireless mouse", "usb c hub"],
  "marketplace": "co.uk",
  "maxResultsPerQuery": 60
}
```

### Frequently asked questions

**Does this scrape Amazon reviews?**
No, and it will not. It returns the review *count* and the star rating from the
product page, which is what a price or ranking model needs. Review text sits
behind a login wall on Amazon, and an actor that promises it either breaks or
does something we are not willing to do.

**How do I monitor the Amazon Buy Box for price changes?**
Put your ASINs in, switch on "Track changes between runs", and schedule the
actor. The first run records the starting state. Every run after that emits a
`change` record whenever the price, the Buy Box seller or the stock status
moves, with the old value, the new value and the percentage move.

**Can I check whether an Amazon seller is a real company?**
Yes, on the EU marketplaces. Either switch on "Verify who the seller really is"
to check whoever holds the Buy Box on your products, or paste the seller IDs
straight into "Sellers to verify by ID". The actor opens the seller's
storefront, reads the legal identity Amazon publishes there, validates the VAT
number against the EU VAT system and matches the business name against the
register. You get a status and a confidence score, and
the disclosed address and country code so a mismatch between "registered in
Germany" and "address in China" is visible at a glance.

**Why does a product sometimes come back with no price?**
Amazon withholds the whole Buy Box, price included, on listings it will not ship
to the region a run exits from. This is the same mechanism as the caveat above. Those rows carry `parseStatus: "no-buy-box"` and
the run's status message says how many there were. Nothing is guessed: a missing
price stays null rather than being filled from a related product.

Amazon also sometimes answers with a cached, price-less copy of the page instead
of rendering the offer. The run retries such a page under a second browser
fingerprint, which normally brings the price back; if even that copy comes back
cached, the row is marked `parseStatus: "degraded-render"` rather than
`no-buy-box`, so a monitor never reads a rendering hiccup as the Buy Box
changing hands. Change records are only ever computed from `full` rows.

**Does it need a proxy or an API key?**
No. There is no proxy setting, no key field and no login. The price you see is
the whole price.

**What happens if Amazon blocks a marketplace mid-run?**
The actor stops that marketplace after the second blocked response instead of
hammering it, names the marketplace and the reason in the run's status message,
and finishes with whatever it did collect. It never reports an empty run as a
clean success.

**How many products can one run handle?**
Up to 2000 ASINs, and up to 1000 search results per keyword. You are charged
only for records actually delivered.

**Can I get alerts somewhere else?**
Yes, through Apify's own integrations. Point a webhook, Slack, or a Google
Sheets integration at the dataset and filter on `recordType = "change"`.

***

Amazon scraper, Amazon Buy Box monitor, Amazon price tracker, Amazon price
monitoring API, Amazon seller verification, Amazon seller lookup, Amazon VAT
check, ASIN scraper, Amazon product data, Amazon search rank tracker, Amazon
BSR tracker, Amazon stock monitor, amazon.de scraper, amazon.co.uk scraper,
Amazon repricing data, Amazon competitor monitoring.

# Actor input Schema

## `asins` (type: `array`):

One ASIN per line, e.g. <code>B00PGB7OKM</code>. They are read on the marketplace chosen below. Each one returns the live Buy Box price, who is winning the Buy Box, who fulfils it, stock wording, rating, review count and Best Sellers Rank.

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

Full Amazon product links, e.g. <code>https://www.amazon.de/dp/B0DK955V6Z</code>. Each URL keeps its own marketplace, so you can watch the same product on amazon.com and amazon.de in one run.

## `searchQueries` (type: `array`):

Keywords to run through Amazon search, e.g. <code>wireless mouse</code>. You get the ranked results with position, price, rating, review count and whether the slot is sponsored, which is how you track where a product sits against its competitors.

## `sellerIds` (type: `array`):

Check a seller's identity without going through a product page. One entry per line: a seller ID (<code>A3GX1RCD4Z9H04</code>), a marketplace and ID together (<code>de:A3GX1RCD4Z9H04</code>), or a pasted storefront link (<code>https://www.amazon.de/sp?seller=A3GX1RCD4Z9H04</code>). A bare ID uses the marketplace chosen below. Each one returns a seller record with the legal identity Amazon publishes and the register check on it. Use this when you already know which sellers you care about, or when a run does not see a third-party Buy Box to start from.

## `marketplace` (type: `string`):

Which Amazon site the ASINs and keywords are read on. Product URLs override this per URL.

## `maxResultsPerQuery` (type: `integer`):

Stop after this many search results for each keyword. You are only charged for results actually delivered.

## `verifySeller` (type: `boolean`):

For each third-party seller holding the Buy Box, open their storefront, read the legal identity EU law makes Amazon publish (business name, registered address, VAT number, trade register number) and check it against an official register: the EU VAT system for amazon.de/fr/it/es, the French company register, or Companies House for amazon.co.uk. You find out whether the "German" seller is a company in Shenzhen. Billed per seller checked, and only when a storefront was actually read.

## `monitorMode` (type: `boolean`):

Remember each product's price, Buy Box seller and stock, and return an extra change record whenever one of them moves. The first run records the starting state; schedule the actor daily and later runs tell you what moved.

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

With change tracking on, leave out every product whose price, Buy Box seller and stock are all unchanged since the last run, so a 500-product watchlist returns a short list instead of 500 rows. Turning this on turns change tracking on.

## Actor input object example

```json
{
  "asins": [
    "B00PGB7OKM",
    "B0BXNR9DB6"
  ],
  "productUrls": [
    "https://www.amazon.de/dp/B0DK955V6Z"
  ],
  "marketplace": "com",
  "maxResultsPerQuery": 20,
  "verifySeller": false,
  "monitorMode": false,
  "onlyChanges": false
}
```

# Actor output Schema

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

Product, search, seller and change records in the default dataset.

# 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 = {
    "asins": [
        "B00PGB7OKM",
        "B0BXNR9DB6"
    ],
    "productUrls": [
        "https://www.amazon.de/dp/B0DK955V6Z"
    ],
    "maxResultsPerQuery": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("tagadanar/amazon-product-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 = {
    "asins": [
        "B00PGB7OKM",
        "B0BXNR9DB6",
    ],
    "productUrls": ["https://www.amazon.de/dp/B0DK955V6Z"],
    "maxResultsPerQuery": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("tagadanar/amazon-product-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 '{
  "asins": [
    "B00PGB7OKM",
    "B0BXNR9DB6"
  ],
  "productUrls": [
    "https://www.amazon.de/dp/B0DK955V6Z"
  ],
  "maxResultsPerQuery": 20
}' |
apify call tagadanar/amazon-product-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tagadanar/amazon-product-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/zTXVrLIHsO0NTKu0d/builds/jiW45RB9eWbDgYhP1/openapi.json
