# Amazon Product & Best Sellers Scraper: Search, Buy Box (`arcadium/amazon-products`) Actor

Amazon product search, Best Sellers ranks and Buy Box offers on 21 stores, $0.54 per 1,000 search rows vs $1 at the two most used search actors. Position, sponsored flag, ASIN, price, rating, badges, bought in past month; Bestsellers, New Releases, Movers. Leader input works. Free error rows.

- **URL**: https://apify.com/arcadium/amazon-products.md
- **Developed by:** [Arcadium Data](https://apify.com/arcadium) (community)
- **Categories:** E-commerce, AI, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.54 / 1,000 search results

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?

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

## Amazon Product & Best Sellers Scraper: Search, Buy Box

Track where products rank for a keyword, watch competitors' prices and sponsored slots, or pull Best Sellers for product research. Give it search terms, Best Sellers categories, ASINs or Amazon links and it returns JSON rows from 21 Amazon stores. Search rows carry position, sponsored flag, ASIN, title, price, list price, rating, rating count, badges and "bought in past month" at $0.54 per 1,000. Best Sellers, New Releases and Movers & Shakers rows carry rank, price and rating for all 100 ranks; product rows per ASIN carry the Buy Box price and seller, ships-from, delivery promise, the star split and every other offer. You pay only for the rows you get.

**Why this actor**

- **Drop-in input.** Input written for `apt_marble/amazon-search-results-scraper` (`keywords`, `maxResultsPerKeyword`, `sortBy`, `excludeSponsored`, `marketplace: "us"`), `santamaria-automations/amazon-search-scraper` (`searchQueries`, `country`, `maxResultsPerQuery`, `maxPages`, `minStars`), `khadinakbar/amazon-product-search-scraper` (`searchQuery`, `maxResults`, `maxSearchPages`) or `junglee/Amazon-crawler` (`categoryOrProductUrls`, `maxItemsPerStartUrl`) works as it is.
- **About half the price per search row.** $0.54 per 1,000 against $1 at apt_marble and santamaria-automations, the two most used Amazon search actors, and $2 at khadinakbar (free plan, Apify Store, 2026-10-31). 51 of our 51 runs since 2026-10-22 succeeded (scheduled and test runs, Apify run history).
- **21 stores, Best Sellers and Buy Box in one actor.** Search, Best Sellers / New Releases / Movers & Shakers ranks and Buy Box + offers per ASIN, with local prices and sellers: non-US stores are read from an IP in their own country (US, DE and JP are checked every day).
- No login, no Amazon account, no customer reviews or reviewer names. Unknown ASINs, bad URLs and temporary blocks come back as free error rows with a `code`.

| Row | Free plan | Business, Platinum and Diamond |
| --- | --- | --- |
| Search result | $0.54 per 1,000 | $0.54 per 1,000 |
| Best Sellers row | $5.31 per 1,000 | $2.88 per 1,000 |
| Product row (Buy Box and offers) | $2.25 per 1,000 | $1.35 per 1,000 |

Built by Arcadium Data: public data, dated and agent-ready, never personal data.

### Use with AI agents

The actor takes plain JSON and returns flat rows, so an AI agent or MCP client (for example through [mcp.apify.com](https://mcp.apify.com)) can call `arcadium/amazon-products` directly. Input example for "What sells for this keyword on amazon.de, ads excluded":

```json
{ "marketplace": "DE", "searches": ["kopfhörer"], "maxResultsPerSearch": 30, "includeSponsored": false }
```

"Top 50 Best Sellers in Electronics on amazon.com":

```json
{ "categories": ["electronics"], "listTypes": ["bestsellers"], "maxResultsPerList": 50 }
```

"Who holds the Buy Box and at what price, plus every other offer":

```json
{ "asins": ["B0DCH8VDXF", "B08JHCVHTY"], "maxOffers": 20 }
```

Read `rowType` first: `searchResult` rows carry `position`, `sponsored`, `asin`, `price`, `rating` and `boughtPastMonth`; `bestseller` rows carry `rank`, `listType` and `categoryName`; `product` rows carry `buyBoxPrice`, `buyBoxSeller`, `starPercent` and `offers`. 100 search rows cost about $0.06 on the free plan. An unknown ASIN or category, a URL we do not read, or a temporary block comes back as a free row with `rowType: "error"`, a `code` (`not_found`, `no_match`, `invalid_input`, `blocked`, `unavailable`) and a `message`, never as a failed run, so an agent can tell "does not exist" from "try again later".

### What you get

| Field | What it holds |
| --- | --- |
| `rowType` | `searchResult`, `bestseller`, `product` or `error`. |
| `marketplace`, `domain`, `currency` | The store (`DE`, `amazon.de`) and the currency of every price on the row (`EUR`). |
| `asin`, `url`, `title`, `imageUrl` | The product, its canonical `/dp/` link and main image. |
| `price`, `priceText`, `listPrice`, `listPriceText` | Price as a number and as shown, and the struck-through list or "Was" price. |
| `rating`, `ratingCount` | Average stars and number of ratings. |
| `searchTerm`, `page`, `position`, `organicPosition`, `sponsored` | Search rows: where the card was, counting ads (`position`) and without them (`organicPosition`). |
| `badges`, `boughtPastMonth`, `boughtPastMonthText`, `deliveryText` | Search rows: "Best Seller", "Amazon's Choice", "Limited time deal"; "1K+ bought in past month" as 1000; the delivery line. |
| `listType`, `category`, `categoryName`, `listTitle`, `rank` | List rows: which list, which category and the rank. |
| `rankChangePercent`, `salesRank`, `salesRankYesterday` | Movers & Shakers rows: the 24-hour rank change. |
| `starPercent` | Product rows: share of ratings per star, e.g. `{ "5": 73, "4": 12, "3": 8, "2": 2, "1": 5 }`. |
| `hasBuyBox`, `buyBoxPrice`, `buyBoxCondition`, `buyBoxSeller`, `buyBoxSellerId`, `buyBoxShipsFrom`, `buyBoxFulfilledByAmazon`, `buyBoxDelivery` | Product rows: the featured offer and who sells and ships it. |
| `otherOfferCount`, `offers` | Product rows: every other offer with condition, price, seller name and id, seller rating, ships from and delivery. |
| `scrapedAt` | When the row was read. |

Output example, a search row:

```json
{
  "rowType": "searchResult",
  "marketplace": "US",
  "domain": "amazon.com",
  "currency": "USD",
  "searchTerm": "wireless earbuds",
  "page": 1,
  "position": 2,
  "organicPosition": null,
  "asin": "B0C1BTXM9W",
  "sponsored": true,
  "title": "Wireless Earbuds, Bluetooth 5.4 Ear Buds LED Power Display Headphones Bass Stereo ...",
  "url": "https://www.amazon.com/dp/B0C1BTXM9W",
  "imageUrl": "https://m.media-amazon.com/images/I/614gb9uXQuL.jpg",
  "price": 19.99,
  "priceText": "$19.99",
  "listPrice": 28.49,
  "listPriceText": "$28.49",
  "rating": 4.3,
  "ratingCount": 14589,
  "badges": [],
  "boughtPastMonth": 6000,
  "boughtPastMonthText": "6K+ bought in past month",
  "deliveryText": "Join Prime to get FREE delivery Tomorrow, Oct 23",
  "scrapedAt": "2026-10-22T08:00:00.000Z"
}
```

A product row:

```json
{
  "rowType": "product",
  "marketplace": "US",
  "domain": "amazon.com",
  "currency": "USD",
  "asin": "B0B7B6KLH3",
  "url": "https://www.amazon.com/dp/B0B7B6KLH3",
  "title": "【Pack of 2】 New Universal Remote for All Samsung TV Remote, Replacement Compatible for All Samsung Smart TV ...",
  "imageUrl": "https://m.media-amazon.com/images/I/41V72RLmv8L.jpg",
  "rating": 4.5,
  "ratingCount": 28619,
  "starPercent": { "5": 79, "4": 9, "3": 4, "2": 2, "1": 6 },
  "hasBuyBox": true,
  "buyBoxPrice": 9.97,
  "buyBoxPriceText": "$9.97",
  "listPrice": null,
  "listPriceText": null,
  "listPriceLabel": null,
  "buyBoxCondition": "New",
  "buyBoxSeller": "HTH.INC",
  "buyBoxSellerId": "A3US3KTV1R02M4",
  "buyBoxShipsFrom": "Amazon.com",
  "buyBoxFulfilledByAmazon": true,
  "buyBoxDelivery": "FREE delivery Tuesday, October 27 on orders shipped by Amazon over $35",
  "otherOfferCount": 1,
  "offers": [
    {
      "condition": "New",
      "price": 11.99,
      "priceText": "$11.99",
      "soldBy": "LOUTOC Direct",
      "sellerId": "ABZD48ETQ2YVP",
      "shipsFrom": "Amazon.com",
      "fulfilledByAmazon": true,
      "sellerRating": 5,
      "sellerRatingCount": 19,
      "sellerPositiveText": "100% positive over last 12 months",
      "deliveryText": "FREE delivery Tuesday, October 27 on orders shipped by Amazon over $35"
    }
  ],
  "source": "B0B7B6KLH3",
  "scrapedAt": "2026-10-22T08:00:00.000Z"
}
```

### Input

```json
{
  "marketplace": "US",
  "searches": ["wireless earbuds", "usb c cable"],
  "categories": ["electronics", "kitchen"],
  "listTypes": ["bestsellers", "new-releases"],
  "asins": ["B0DCH8VDXF"],
  "urls": ["https://www.amazon.de/gp/bestsellers/ce-de", "https://www.amazon.co.uk/s?k=charger"],
  "maxResultsPerSearch": 48,
  "maxResultsPerList": 50
}
```

| Field | What it does |
| --- | --- |
| `marketplace` | Store for searches, categories and ASINs: `US`, `GB`, `DE`, `FR`, `IT`, `ES`, `CA`, `JP`, `AU`, `IN`, `MX`, `BR`, `NL`, `SE`, `PL`, `BE`, `TR`, `AE`, `SA`, `SG`, `EG`. URLs use their own store. |
| `searches` | Keywords. Each gives up to `maxResultsPerSearch` rows (default 48, up to 1,000) over as many result pages as needed. |
| `categories`, `listTypes` | Category paths as in Best Sellers URLs (`electronics`, `electronics/172541`, `ce-de` on amazon.de) and which lists to read: `bestsellers` (default), `new-releases`, `movers-and-shakers`, `most-wished-for`, `most-gifted`. |
| `maxResultsPerList` | Ranks per list, up to 100 (default 50). |
| `asins` | Product rows: Buy Box, offers and star split per ASIN. |
| `urls` | Search URLs (filters kept), list URLs and product URLs of any of the 21 stores. |
| `sort`, `minPrice`, `maxPrice` | Search order (`relevance`, `priceAsc`, `priceDesc`, `rating`, `newest`, `bestSellers`) and price range, applied by Amazon. |
| `minRating`, `includeSponsored` | Drop results below a star rating, or drop ads. Skipped cards are free. |
| `includeProductRows` | Also read the product row of every ASIN a search or list found (charged as product rows). |
| `maxOffers` | Other offers per product row (default 10, up to 20). |
| `maxItems` | Stop after this many charged rows in total. A cost cap. |
| `includeErrorRows` | A free row for every input without data (on by default). |

Input names of the most used Amazon scrapers are accepted as they are (`categoryOrProductUrls` and `startUrls` with `{ "url": ... }` objects, `categoryUrls`, `maxItemsPerStartUrl`, `maxSearchPagesPerStartUrl`, `countryCode`, `amazonDomain`, `asins`, `searchQueries`, `country`, `maxResultsPerQuery`, `maxPages`, `maxResults`, `sortBy`, `minStars`, `includeSponsored`, `Params`, `website`, `queries`, `maxOffers`, `retries`, `keywords`, `maxResultsPerKeyword`, `excludeSponsored`, lowercase `marketplace` codes, `searchQuery`, `maxSearchPages`), so an existing input can be pasted in. Not supported and ignored: `primeOnly`, `language`, `enrichDetails` (turn on `includeProductRows` for product details; they are charged as product rows).

### Use it from code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("arcadium/amazon-products").call(run_input={
    "marketplace": "GB",
    "searches": ["phone charger"],
    "maxResultsPerSearch": 60,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    if item["rowType"] == "searchResult":
        print(item["position"], item["sponsored"], item["priceText"], item["title"][:60])
```

JavaScript:

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('arcadium/amazon-products').call({
  asins: ['B0DCH8VDXF', 'B08JHCVHTY'],
  maxOffers: 20,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const p of items.filter((i) => i.rowType === 'product')) console.log(p.asin, p.buyBoxPriceText, p.buyBoxSeller);
```

### Pricing

You pay per row delivered, at the price of your Apify plan. Error rows, repeats, skipped ads and results below your star filter are free.

| Apify plan | Per 1,000 search results | Per 1,000 Best Sellers rows | Per 1,000 product rows |
| --- | --- | --- | --- |
| Free | $0.54 | $5.31 | $2.25 |
| Starter (Bronze) | $0.54 | $4.50 | $1.80 |
| Scale (Silver) | $0.54 | $3.69 | $1.53 |
| Business (Gold) | $0.54 | $2.88 | $1.35 |
| Platinum | $0.54 | $2.88 | $1.35 |
| Diamond | $0.54 | $2.88 | $1.35 |

Plus a one-off $0.001 per GB of memory when a run starts.

Set a maximum cost per run in the Apify run options and the actor stops before it goes over.

Watch mode (below): new and changed rows are charged as above. From the second run of a watch key on, each unchanged row costs a small check event, on every plan: search row $0.50, Best Sellers row $0.10, product row $0.85 per 1,000 (`search-check`, `bestseller-check`, `product-check`). The run still reads every page, and a search page costs about the same to read whether its cards moved or not. The first run of a watch key is a normal run, charged normally.

### Watch mode: pay only for changes

Set `"watch": true` and a `watchKey` (for example `"earbuds-us"`), then run the same input on an Apify schedule. The first run has nothing to compare with: it is a normal run, returns every row and is charged normally, and it saves a snapshot. Every later run with the same key returns only new rows and rows where something a seller watches changed, each with a `change` object:

- search rows: rank (organic position, or position for ads), price, list price, rating, badges, bought in past month;
- Best Sellers rows: rank, price, rating (identified by list + ASIN, so a rank move is a change, not a new row);
- product rows: Buy Box present, Buy Box price, list price, seller, condition, fulfilled by Amazon, other offer count, rating.

```json
{
  "type": "changed",
  "fields": [{ "field": "rank", "old": 7, "new": 6 }, { "field": "price", "old": null, "new": 39.95 }],
  "previousCheckAt": "2026-10-31T13:07:13.631Z"
}
```

Rating counts and delivery dates are left out because they move on almost every run. Search ranks move a lot: in our test, two runs 36 seconds apart changed 26 of 30 search rows (20 rank moves, 6 new), while 0 of 20 Best Sellers rows changed. Watch mode saves most on Best Sellers and product rows. Every watch run also adds one free `watch-summary` row: `checked`, `unchanged`, `changed`, `new`, `gone` (in the last snapshot, not found now), `delivered`, `checksCharged`, `firstRun`, `previousCheckAt` and `complete` (false when the run stopped early, e.g. at your cost limit: then nothing counts as gone and changes that were not delivered come again next run). The snapshot is kept in a named store (`amazon-products-watch`) in your account; use one `watchKey` per input you monitor.

### Weekly digest

Add `"digest": true` to a watch run to get one more free row, `rowType: "watch-digest"`, that sums up the changes of the last `digestDays` days (default 7, up to 90) for this `watchKey`: `new`, `changed`, `gone`, `byType` (counts per change type), `topMoves` (the 5 biggest moves per metric and direction, largest relative change first, each with `label`, `old`, `new`, `delta`, `pct`), `runs` in the window, `windowStart`, `windowEnd`, `previousDigestAt` and `summary`: one plain-text line an AI agent or a workflow can paste into an email or Slack message as it is. The window is rolling: put the watch on a daily schedule and every run's digest covers the last 7 days, or run weekly and read one digest a week. The first run of a key only saves the baseline and its rows are not counted as changes. The window is kept as a second record in the same key-value store as the snapshot. The digest row is free; there is no extra event.

Change types: `price_drop`, `price_rise` (price or Buy Box price), `rank_move`, `buy_box` (seller, condition or Buy Box present changed), `changed` (anything else) and `new`. `topMoves` ranks `price`, `buyBoxPrice`, `rank` and `rating`; labels are the ASIN and the start of the title. Example `summary` (illustrative values):

```text
amazon watch "earbuds-us", last 7 days (7 runs): 12 new, 85 changed, 9 gone. rank moves 61, price drops 14, price rises 10. Biggest price drop: B0EXAMPLE1 Wireless Earbuds ... 49.99 -> 34.99, -30%. Biggest rank rise: B0EXAMPLE2 ... 3 -> 18, +500%.
```

For `rank`, a rise is a higher number, i.e. a worse position.

### Related actors

- [Etsy Scraper: Product Listings, Prices, Tags, Shop Sales](https://apify.com/arcadium/etsy-products)

### Use cases

- Price and Buy Box monitoring: who holds the Buy Box for your ASINs, at what price, and which sellers undercut it, on a daily schedule.
- Keyword and shelf research: where your product and your rivals rank for a search, organic and sponsored, with "bought in past month".
- Category trends: Best Sellers, New Releases and Movers & Shakers per category and store, all 100 ranks.
- Cross-border pricing: the same ASIN on amazon.com, .co.uk, .de and .co.jp in local currency.
- Agents: "find the top-rated products for X under $50 and tell me who sells them".

### Limitations

- Search, ranked lists and the light product row only. The full product page (bullets, brand, BSR, variations, dimensions) is not part of this actor.
- Customer reviews are not collected: Amazon shows them only to signed-in visitors, and we never sign in.
- Delivery and prices are those of a shopper in the store's country without a postcode; a specific postcode needs a sign-in, so it is not supported.
- Search results follow Amazon's own ranking and personalisation for a logged-out visitor; ads and positions move during the day.
- Amazon answers some requests with a captcha or a "Something went wrong" page. The actor retries those on a new IP; inputs that still fail come back as free `blocked` or `unavailable` rows.

### Privacy

Public storefront data only, read the way a logged-out shopper's browser reads Amazon. No login, no account, no cookies of a user, no captcha solving. Seller names are the business names Amazon shows on the offer; no customer, reviewer or buyer data is collected.

### FAQ

**Why do non-US stores cost the same but run a little slower?**
They are read from an IP in their own country, so prices, sellers and delivery are the local ones (a US IP sees export prices). Those IPs are slower than our datacenter IPs.

**A category returned nothing. Why?**
Look at its error row: `not_found` means the category path does not exist on that store (paths differ per store, e.g. `ce-de` on amazon.de); `no_match` means Amazon shows the list as empty right now (Movers & Shakers is often empty, at times in every category of a store); `unavailable` means the page could not be read. These rows are free.

**How fast is it?**
Search: about 50 results per second. Ranked lists: 50 ranks in about two seconds. Product rows: about two per second.

**Something looks wrong in the output. Who do I tell?**
Open an issue on the actor page with the run link. We read them all.

# Actor input Schema

## `searches` (type: `array`):

Keywords to search on the chosen store, e.g. \["wireless earbuds", "usb c cable"]. Each term gives up to maxResultsPerSearch result rows in Amazon's order: position, sponsored flag, ASIN, title, price, list price, rating, rating count, badges, bought in past month. Also read from keywords, searchQueries, searchQuery or queries (other Amazon actors' names).

## `categories` (type: `array`):

Category paths as in the store's Best Sellers URLs, e.g. \["electronics", "electronics/172541", "kitchen"] (amazon.de: "ce-de"). Each category gives one ranked list per listTypes entry, up to maxResultsPerList ranks. A Best Sellers URL works here too.

## `listTypes` (type: `array`):

Which ranked lists to read for every category: Best Sellers (default), New Releases, Movers & Shakers (biggest 24-hour gainers, with the rank change), Most Wished For, Gift Ideas.

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

Product ids, e.g. \["B0DCH8VDXF", "B08JHCVHTY"]. Each gives one product row: title, image, rating, star split, rating count, Buy Box price and seller, list price, ships from, delivery promise, and the other offers (condition, price, seller).

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

Any mix of search URLs (https://www.amazon.com/s?k=yoga+mat, filters kept), Best Sellers / New Releases / Movers & Shakers URLs (https://www.amazon.de/gp/bestsellers/kitchen) and product URLs (https://www.amazon.co.uk/dp/B0DCH8VDXF). Each URL is read on its own store.

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

Store for searches, categories and ASINs (URLs use their own store). Prices, sellers and delivery are those a shopper in that country sees: non-US stores are read from an IP in their country. Example: DE. Lowercase codes (us, uk, de) and the names country, countryCode, amazonDomain or website are accepted too.

## `maxResultsPerSearch` (type: `integer`):

Result rows per search term or search URL, 1 to 1,000 (default 48). Amazon shows 16-60 cards per page; the actor reads as many pages as needed. Sponsored cards count unless includeSponsored is off. Also read from maxResultsPerKeyword or maxResultsPerQuery.

## `maxPagesPerSearch` (type: `integer`):

Upper bound of result pages per search term, 1 to 20 (default 20). Amazon itself stops after about 7 to 20 pages. Also read from maxPages or maxSearchPages.

## `maxResultsPerList` (type: `integer`):

Ranks per Best Sellers / New Releases / Movers & Shakers list, 1 to 100 (default 50). Ranks 51-100 come from the list's second page.

## `sort` (type: `string`):

Order of search results: Amazon's relevance (default), price low to high, price high to low, average rating, newest, best sellers.

## `minPrice` (type: `number`):

Search filter in the store's currency, e.g. 10 for $10 on amazon.com. Applied by Amazon.

## `maxPrice` (type: `number`):

Search filter in the store's currency, e.g. 50 for €50 on amazon.de. Applied by Amazon.

## `minRating` (type: `number`):

Keeps only search results rated at least this (0 to 5, e.g. 4). Skipped results are free.

## `includeSponsored` (type: `boolean`):

Keeps sponsored (ad) cards in search results, flagged with sponsored: true. Turn off to get organic results only; skipped ads are free. Default: true. excludeSponsored: true (another actor's name) means the same as false here.

## `includeProductRows` (type: `boolean`):

Also reads the product row (Buy Box, sellers, offers, star split) of every ASIN a search or list returned. Each product row is charged as a product row. Off by default.

## `maxOffers` (type: `integer`):

Other offers (besides the Buy Box) listed in a product row, 0 to 20 (default 10). Offers 11-20 take one more small request.

## `maxItems` (type: `integer`):

Stops the run after this many charged rows (search, list and product rows together), 1 to 1,000,000. A cost cap; leave empty for no limit.

## `watch` (type: `boolean`):

Compare every row with the last run that used the same watch key and output only new rows and rows whose rank, price, rating, badges or Buy Box changed, each with a change object (fields old -> new). Unchanged rows are not output and not charged; one free watch-summary row counts unchanged, changed, new and gone. The first run is a normal run, charged normally.

## `watchKey` (type: `string`):

Name of the saved snapshot for watch mode (letters, digits, - and \_, up to 60). Use one key per monitored search or list set, for example "weekly-check". A new key starts a new baseline. The snapshot is kept in a key-value store in your account.

## `digest` (type: `boolean`):

Watch mode only. Adds one free watch-digest row per run that sums up the changes of the last digest days for this watch key: counts by change type, price drops and rises, rank moves, the biggest price, Buy Box price and rank moves, and a one-line plain-text summary you can paste into an email or Slack. No extra charge.

## `digestDays` (type: `integer`):

How many days the digest row covers (rolling window, 1-90). Runs older than this drop out of the digest.

## `includeErrorRows` (type: `boolean`):

Adds a free row (rowType error, with a code and message) for every search, category, ASIN or URL that gave no data: not found, invalid input, nothing matched, temporarily blocked. On by default.

## `maxRetries` (type: `integer`):

Advanced. How often a request is retried after a block or temporary error (each retry uses a new IP), 0 to 10 (default 5).

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

Advanced. Leave empty: the actor picks the IPs itself (residential IPs of the store's country for prices, cheaper datacenter IPs where they show the same data) and rotates them.

## Actor input object example

```json
{
  "searches": [
    "wireless earbuds"
  ],
  "categories": [],
  "listTypes": [
    "bestsellers"
  ],
  "asins": [],
  "urls": [],
  "marketplace": "US",
  "maxResultsPerSearch": 20,
  "maxResultsPerList": 50,
  "includeSponsored": true,
  "includeProductRows": false,
  "maxOffers": 10,
  "watch": false,
  "watchKey": "default",
  "digest": false,
  "digestDays": 7,
  "includeErrorRows": true
}
```

# Actor output Schema

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

All rows of this run in the default dataset.

## `view_overview` (type: `string`):

No description

## `view_bestsellers` (type: `string`):

No description

## `view_products` (type: `string`):

No description

## `view_offers` (type: `string`):

No description

## `view_errors` (type: `string`):

No description

## `record_stats` (type: `string`):

Requests, data volume per proxy tier (wire size), IP sessions, retries, breaker pauses and cost per result for this run.

# 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 = {
    "searches": [
        "wireless earbuds"
    ],
    "categories": [],
    "asins": [],
    "urls": [],
    "marketplace": "US",
    "maxResultsPerSearch": 20,
    "includeSponsored": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("arcadium/amazon-products").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 = {
    "searches": ["wireless earbuds"],
    "categories": [],
    "asins": [],
    "urls": [],
    "marketplace": "US",
    "maxResultsPerSearch": 20,
    "includeSponsored": True,
}

# Run the Actor and wait for it to finish
run = client.actor("arcadium/amazon-products").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 '{
  "searches": [
    "wireless earbuds"
  ],
  "categories": [],
  "asins": [],
  "urls": [],
  "marketplace": "US",
  "maxResultsPerSearch": 20,
  "includeSponsored": true
}' |
apify call arcadium/amazon-products --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,arcadium/amazon-products"
        }
    }
}
```

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/4NPTnEcoCe2ygFP2Y/builds/ES5pUuivppWQChusV/openapi.json
