# Amazon Product Scraper — Search, Price, Rating & Reviews (`scrapersdelight/amazon-product-scraper`) Actor

Type a keyword, get Amazon products: ASIN, title, brand, price, currency, rating, review count, sponsored flag and image — plus availability, feature bullets and the full hi-res gallery on demand. 12 marketplaces, keyword or ASIN/URL input, deduped on ASIN. $4.50 per 1,000, no start fee. No login.

- **URL**: https://apify.com/scrapersdelight/amazon-product-scraper.md
- **Developed by:** [Scrapers Delight](https://apify.com/scrapersdelight) (community)
- **Categories:** E-commerce
- **Stats:** 1 total users, 1 monthly users, 88.2% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.50 / 1,000 per product returneds

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?

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 Product Scraper — Search, Price, Rating & Reviews

Type a keyword into [Amazon](https://www.amazon.com) and get products back. One row per **ASIN**, carrying
**asin**, **title**, **brand**, **price**, **priceRaw**, **currency**, **rating**, **reviewCount**, **sponsored**,
**image**, **url**, **searchTerm**, **domain** and **scrapedAt** — plus **availability**, **inStock**,
**features** (the whole bullet list) and **images** (the full hi-res gallery, median ~20 per product) when you
switch on full product detail.

Feed it search terms, product URLs, bare ASINs, or all three in one run — everything lands in one dataset,
deduplicated on ASIN. Works on 12 marketplaces (`.com`, `.co.uk`, `.de`, `.ca`, `.com.au`, `.fr`, `.es`, `.it`,
`.in`, `.co.jp`, `.com.mx`, `.com.br`), and the proxy exit country follows the marketplace automatically.
**No login. No cookies. No Amazon account. No CAPTCHA solving.**

**Scope, measured 2026-08-13, not quoted from a marketing page:** one keyword is worth a few hundred products.
An uncapped walk of `running shoes` on amazon.com ran out after 8 pages of cards and returned **378 raw result
cards → 308 unique ASINs**; page 8 contributed 3 of those 308. Volume here comes from running many keywords,
not from digging one.

#### Quick start

```json
{ "searchTerms": ["wireless earbuds"], "maxItems": 20, "fetchProductDetails": false }
```

That is literally the input the actor ships with — click **Try for free** and hit **Start**, no edits.
Verified 2026-08-13 on the Apify platform (build 0.1.5, this exact input, nothing typed): **20 rows in 7.5 seconds**, charged **20 × $0.0045 = $0.09**.

***

### The wedge: full product detail costs time, not money

Every product is **$0.0045**, whether the row is a search card or a complete product page. Turning on
`fetchProductDetails` adds one request per product — it does **not** add a charge, a per-offer fee, a
per-seller fee or a delivery-location fee. Measured on 40 live products (2026-08-13), that upgrade is worth:

| | Search card only | With full product detail |
|---|---|---|
| title / price / image | 100% | 100% |
| rating / reviewCount | 99%+ | 97.5–100% |
| availability | — | 97.5–100% |
| features (bullet list) | — | **100%**, median 5 bullets |
| images (hi-res gallery) | — | **100%**, median 20–21 images |
| brand | 93.5% *or* 0%, depending on card layout (see limits) | **90–92.5%** |
| Wall-clock, measured | 20 rows in 7.5 s | 40 rows in 1 min 58 s |
| Price per product | $0.0045 | $0.0045 |

The second thing this actor does that the depth-focused Amazon scrapers do not: **search terms and product
URLs/ASINs in the same run**, reconciled on ASIN. You can hand it `["wireless earbuds"]` and a list of 200
competitor ASINs and get one clean deduplicated table out.

### Read this before you buy rows

1. **Search cards and product pages are the same schema but not the same row.** A `source: "search"` row has
   `brand`/`availability`/`features`/`images` at or near null — the card never carried them. `source:
   "product"` and `source: "search+detail"` rows have them. Plan against the right fill table below.
2. **Amazon repeats itself across pages.** 378 raw cards on the `running shoes` walk collapsed to 308 unique
   ASINs (18.5% repeats). We dedupe on ASIN *before* billing, so you pay 308, not 378 — but it means a
   "12-page" run is not 12 pages of new products.
3. **One keyword bottoms out.** After ~7 pages Amazon starts serving 12-card pages of mostly-seen products and
   then nothing. If you need 10,000 rows, that is 30–50 keywords, not one keyword and a big `maxPagesPerTerm`.
4. **This is a listing-and-detail scraper, not a sales-intelligence product.** There is no Best Sellers Rank,
   no estimated monthly sales, no seller/offer objects, no variant matrix, no review text. See *Honest limits*
   for who to buy that from instead.
5. **A `price` of `null` is a real inventory state** ("Currently unavailable"), not a parse miss. It was
   1 row in 308 on the search walk.

### What you get — one row per ASIN

| Group | Fields |
|---|---|
| Identity | `asin`, `url` (always a canonical `/dp/<asin>` or full product URL), `title` |
| Money | `price` (number), `priceRaw` (the string Amazon rendered), `currency` (ISO code, resolved from the marketplace) |
| Social proof | `rating` (0–5 stars), `reviewCount` (integer count of ratings) |
| Merchandising | `brand`, `sponsored` (`true` = an Amazon ad placement) |
| Detail-only | `availability` (the stock sentence), `inStock` (boolean), `features` (array of bullets), `images` (array of hi-res gallery URLs) |
| Media | `image` (the thumbnail on search rows, the first gallery image on detail rows) |
| Provenance | `source` (`search` / `product` / `search+detail`), `searchTerm`, `domain`, `scrapedAt` (ISO-8601 UTC) |

`price` is a number in the marketplace's currency; `rating` is on a 0–5 scale, never a percentage. A field is
`null` when Amazon did not publish it; arrays are `null` rather than `[]` when the row never visited a product
page.

### Field fill — measured 2026-08-13

All figures below come from runs of the shipped build through Apify residential proxy. No home-broadband probe is reported anywhere on this page.

**A. Search rows** — 308 unique ASINs, the complete uncapped walk of `running shoes` on amazon.com.

| Field | Fill |
|---|---|
| `asin`, `url`, `title`, `image`, `sponsored`, `searchTerm`, `domain`, `scrapedAt` | **308/308 = 100%** |
| `rating`, `reviewCount` | **308/308 = 100%** |
| `price`, `priceRaw`, `currency` | 307/308 = 99.7% |
| `brand` | 288/308 = 93.5% *(this card layout only — see below)* |
| `availability`, `inStock`, `features`, `images` | 0% — search cards do not carry them |

**B. Full-detail rows** — two independent 40-product `wireless earbuds` runs with
`fetchProductDetails: true` (run A and run B, both 2026-08-13). Both recovered 40 of 40 product pages.
Where the two runs disagree, both numbers are printed rather than the flattering one.

| Field | Run A | Run B |
|---|---|---|
| `title`, `price`, `currency`, `image` | **40/40 = 100%** | **40/40 = 100%** |
| `features` | **100%** (median 5 bullets) | **100%** (median 5 bullets) |
| `images` | **100%** (median 21) | **100%** (median 20) |
| `rating`, `reviewCount` | 40/40 = 100% | 39/40 = 97.5% |
| `availability` | 40/40 = 100% | 39/40 = 97.5% |
| `inStock` | 100% | 100% — see the caveat below |
| `brand` | 36/40 = 90% | 37/40 = 92.5% |

`inStock` reaches 100% partly by inference: when a product page publishes no `availability` sentence
but does publish a buyable price, `inStock` is set `true`. Read `availability` when you need the
observed string rather than the derived boolean.

**The headline that could mislead you:** `brand` was 93.5% on the `running shoes` search walk and **0 of 22 on
the `wireless earbuds` search walk**. Amazon serves two search-card layouts; only the newer one prints a brand
line above the title. If you need brand on every row, turn on `fetchProductDetails` (90% there) rather than
relying on the card.

Every run prints its own measured fill in the log, e.g.
`Field fill on 40 row(s) (40 with product-page detail): title 100% · price 100% · … · brand 90%`.

### How to run it

**Keyword search (the default).** Cheapest and fastest. One request per results page.

```json
{ "searchTerms": ["wireless earbuds", "bone conduction headphones"], "maxItems": 200, "maxPagesPerTerm": 7 }
```

**Keyword search plus full detail.** One extra request per product; the price per product is unchanged.

```json
{ "searchTerms": ["wireless earbuds"], "maxItems": 40, "fetchProductDetails": true }
```

**A list of products you already know.** URLs with or without the `/ref=` tail, `/gp/product/` URLs and bare
10-character ASINs are all accepted in the same array, and always come back as full product pages.

```json
{ "productUrls": ["https://www.amazon.com/dp/B09B8V1LZ3", "B0BQPNMXQV", "https://www.amazon.com/JBL-Vibe-Buds-Wireless-Headphones/dp/B0BQPZ7DMV/ref=sr_1_20"] }
```

**A non-US marketplace.** Set `domain` and nothing else — the proxy country follows it.

```json
{ "searchTerms": ["kettle"], "domain": "amazon.co.uk", "maxItems": 50 }
```

**Diagnose a bad run without paying for it.**

```json
{ "searchTerms": ["wireless earbuds"], "diagnose": true }
```

### Sample rows

A real search row, from the `running shoes` walk:

```jsonc
{
  "asin": "B0CKMC1BGB",
  "url": "https://www.amazon.com/adidas-Racer-Adapt-Sneaker-Black/dp/B0CKMC1BGB/ref=sr_1_2",
  "title": "Men's Lite Racer Adapt 7.0 Running Shoes",
  "brand": "adidas",

  "price": 49,
  "priceRaw": "$49.00",
  "currency": "USD",

  "rating": 4.4,
  "reviewCount": 8170,
  "sponsored": false,

  "availability": null,
  "inStock": null,
  "features": null,
  "images": null,
  "image": "https://m.media-amazon.com/images/I/71DRTGuiksL._AC_UL320_.jpg",

  "source": "search",
  "searchTerm": "running shoes",
  "domain": "amazon.com",
  "scrapedAt": "2026-08-13T02:29:34.291Z"
}
```

A real `search+detail` row (bullets and gallery truncated here for length — the actual row carries all 10
bullets and all 36 image URLs):

```jsonc
{
  "asin": "B09FT58QQP",
  "url": "https://www.amazon.com/dp/B09FT58QQP",
  "title": "TOZO A1 Wireless Earbuds Bluetooth 5.3 Light Weight in Ear IPX5 Waterproof Headphones 2 Mic for AI Calls…",
  "brand": "TOZO",

  "price": 13.99,
  "priceRaw": "$13.99",
  "currency": "USD",

  "rating": 4.3,
  "reviewCount": 116348,
  "sponsored": false,

  "availability": "In Stock",
  "inStock": true,
  "features": [
    "[Ultra-Lightweight Ear Buds Designed for Small Ears] Each earbud weighs only 3.7g …",
    "[Immersive Stereo Sound with TOZO OrigX Technology] TOZO OrigX tuning delivers clear vocals …"
    // 10 bullets in total
  ],
  "image": "https://m.media-amazon.com/images/I/81+4jNKVFgL._AC_SL1500_.jpg",
  "images": [
    "https://m.media-amazon.com/images/I/81+4jNKVFgL._AC_SL1500_.jpg",
    "https://m.media-amazon.com/images/I/71KW9rwx7KL._AC_SL1500_.jpg"
    // 36 images in total
  ],

  "source": "search+detail",
  "searchTerm": "wireless earbuds",
  "domain": "amazon.com",
  "scrapedAt": "2026-08-13T02:32:11.770Z"
}
```

Fields people misread:

- `rating` is stars out of 5 (`4.3`), never a percentage. `reviewCount` is Amazon's count of ratings.
- `image` is a ~320 px thumbnail on search rows and a full-size gallery image on detail rows — they are
  different sizes of the same product shot, not a fill inconsistency.
- `sponsored: true` marks an ad placement, not a different kind of product. Sponsored cards link through an
  ad redirect; the `url` you get is the resolved product page, never the tracker.
- `features: null` means the row never opened a product page. It does not mean the product has no bullets.

### Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `searchTerms` | array of strings | `["wireless earbuds"]` | Keywords as typed into Amazon's search box. A results page carries 16–60 cards depending on the query and the day. |
| `productUrls` | array of strings | — | Product URLs, `/gp/product/` URLs or bare ASINs. Always fetched as full product pages and billed once each. |
| `maxItems` | integer | `20` | Unique products to stop at, across all inputs. **Your cost cap**: 20 = $0.09, 1,000 = $4.50. `0` = no cap. Duplicates never count against it. |
| `maxPagesPerTerm` | integer | `5` | Search pages per term. Amazon serves ~7 useful pages then repeats; higher values buy time, not rows. |
| `includeSponsored` | boolean | `true` | Keep ad placements (30 of 308 = 9.7% and 56 of 322 = 17.4% on two `running shoes` walks — ad density moves). Dropped cards are never charged. |
| `fetchProductDetails` | boolean | `false` | Open each search result's product page for brand, availability, features and gallery. One extra request per product; **same $0.0045 either way**. |
| `domain` | select | `amazon.com` | Which of the 12 marketplaces. Sets the proxy country and the currency labelling. |
| `proxyConfiguration` | proxy | Apify **RESIDENTIAL**, country auto | Residential is required — see the ladder below. Pinning a country here overrides the marketplace default. |
| `requestConcurrency` | integer | `4` | Parallel product-page requests during the detail pass. Clamped to 6; Amazon tightens its block rate under burst load. |
| `diagnose` | boolean | `false` | Probe two search pages plus one product page, dump the raw HTML and a parse report to the key-value store, then exit **without writing a row or charging anything**. |

#### Marketplaces

`amazon.com` (USD) · `amazon.co.uk` (GBP) · `amazon.de` (EUR) · `amazon.ca` (CAD) · `amazon.com.au` (AUD) ·
`amazon.fr` (EUR) · `amazon.es` (EUR) · `amazon.it` (EUR) · `amazon.in` (INR) · `amazon.co.jp` (JPY) ·
`amazon.com.mx` (MXN) · `amazon.com.br` (BRL)

### Pricing

**$0.0045 per product returned — $4.50 per 1,000.** Charged on the `product-scraped` event. No actor-start
fee, and no monthly platform fee from this Actor.

You are charged for unique products delivered. You are **not** charged for search-result pages, for the
product-page fetch that `fetchProductDetails` performs, for a request we had to retry through the anti-bot
challenge, for a sponsored card your `includeSponsored: false` filter removed, or for the same ASIN twice.
Rows are charged as they are pushed, so if you hit a budget cap you get whole rows and stop, never a
half-billed dataset.

| Run | Products | Cost |
|---|---|---|
| The prefilled default run | 20 | $0.09 |
| A 40-product run with full detail | 40 | $0.18 |
| The complete `running shoes` walk, measured | 308 | $1.39 |
| A thousand rows | 1,000 | $4.50 |
| Ten thousand rows (≈30–50 keywords) | 10,000 | $45.00 |

`maxItems` is the hard cost cap (default 20; set `0` for uncapped).

### Honest limits

- **No Best Sellers Rank, no sales estimates, no seller or offer objects, no variant matrix, no review text,
  no Q\&A.** This actor returns what a search card and a product page publish, and nothing inferred. If you
  need BSR or estimated monthly sales, `automly/amazon-products-scraper---fast-efficient-with-sales-data`
  models them; if you need per-offer and per-seller depth on a URL you already have,
  `junglee/Amazon-crawler` returns it. Both charge extra per offer/seller or a start fee; that is the trade.
- **`brand` on search rows is layout-dependent: 93.5% on one card layout and 0 of 22 on the other.** That is
  Amazon serving two templates, not a parse failure. `fetchProductDetails: true` gets brand from the product
  page byline at 90–92.5%.
- **`brand` is 90–92.5%, not 100%, even on product pages.** 3–4 of 40 products had no `#bylineInfo` byline to
  read. A missing brand means Amazon published none for that ASIN.
- **`availability` and `rating` are not guaranteed on a product page either.** Two 40-product runs measured
  40/40 and 39/40 on each. `inStock` is derived from `availability`, falling back to "has a buyable price"
  when Amazon printed no stock sentence — so `inStock` can be `true` on a row whose `availability` is `null`.
- **A single keyword tops out at a few hundred ASINs.** 308 unique for `running shoes`; the 8th page added 3.
- **18.5% of raw search cards are repeats** of an ASIN already seen on an earlier page. They are dropped
  before billing, but they are why page 6 of a walk is worth less than page 2.
- **Only 4 of the 12 marketplaces are live-verified**: amazon.com, amazon.co.uk, amazon.de and amazon.ca were
  each run end-to-end on 2026-08-13. The other eight use the identical code path and the same country-matched
  proxy, but they have not been individually measured and are not being claimed as measured.
- **Currency is resolved from the marketplace, not only the symbol.** `$39.99` on amazon.ca is labelled `CAD`,
  not `USD`. `priceRaw` always preserves exactly what Amazon rendered, so you can check.
- **Residential proxy is mandatory** and it is billed to your Apify account separately from this Actor's
  per-product price. A single datacenter attempt cleared 2 of 20 (see the ladder).
- **It does not log in, does not solve CAPTCHAs and buys no CAPTCHA-solving service.** When the anti-bot
  challenge appears, the actor throws away that session and tries a fresh one. That is the whole technique.

### How it works, and the transport ladder

Two plain HTTP endpoints, no browser and no API key: `GET /s?k=<query>&page=N` for search cards and
`GET /dp/<asin>` for product pages, parsed with cheerio. Gallery images come out of the `colorImages` /
`ImageBlockATF` JavaScript blob the product page ships, with a `hiRes`/`large` regex fallback.

Amazon answers some requests with a short per-session anti-bot stub instead of the page. It is per-session, so
every attempt is issued on a **brand-new proxy session** and a blocked attempt is simply retried on a fresh
one. Measured through Apify on 2026-08-13, single attempt, N=20 per rung:

| Rung | Result |
|---|---|
| Apify datacenter proxy, auto group | **2/20 = 10%** |
| Apify RESIDENTIAL, country matched to the marketplace | **12/20 = 60%** |
| RESIDENTIAL + fresh-session retry (what the actor ships) | **45 of 45 target pages delivered = 100%**, from 54 HTTP attempts — 1.20 attempts per page |

Country matters as much as tier: `amazon.co.uk` failed **6 of 6** attempts from a US residential exit and
returned 22 cards on the **2nd** attempt from a GB one. `amazon.de` served a US exit prices in **USD** with
English availability text, and a DE exit prices in **EUR** on the first attempt. That is why the proxy country
follows the `domain` you pick unless you override it.

Concurrency is capped at 6 on purpose; the detail pass runs at 4 and search pages are walked sequentially with
a 300 ms gap.

### Uniqueness and dedupe

Products are keyed on **ASIN** and deduplicated *before* anything is fetched or charged, so the dataset — and
your bill — never holds the same product twice. Measured on **contiguous** page walks (sparse sampling would
have hidden this):

| Walk | Raw cards | Unique ASINs | Repeats |
|---|---|---|---|
| `running shoes`, all 8 pages | 378 | 308 | **18.5%** |
| `running shoes`, all 8 pages, repeated on a second run | 390 | 322 | 17.4% |
| `running shoes`, pages 1–5 | 300 | 248 | 17.3% (26 sponsored repeats, 26 organic) |
| `wireless earbuds`, pages 1–5 | 104 | 75 | 27.9% |

A `diagnose` probe on 2026-08-13 found page 2 repeating **8 of page 1's 22** ASINs. The mechanism is Amazon's
own: sponsored slots re-serve the same ad on several pages, and organic results shuffle between pages within a
query. Search terms and `productUrls` also reconcile against each other — hand it a keyword and an ASIN that
the keyword also returns and you are billed once.

Runs are independent: two runs of the same keyword will return overlapping ASINs. Dedupe across runs on
`asin` in your own store.

### When a run comes back short

- **An input that names no work runs the documented sample instead of erroring.** Start the actor with an
  empty input and it logs a warning naming the fields to set (`searchTerms`, `productUrls`) and runs
  `"wireless earbuds"` on the selected marketplace, capped at 20 products ($0.09). Set your own terms to
  replace it.
- **Zero rows never succeeds *silently*, but it never fails either.** If Amazon soft-blocked every attempt,
  or the keyword matched nothing, the run exits cleanly with a status message saying so and **nothing is
  charged** — billing is attached to the rows pushed, so an empty run costs $0.
- **A search page that cannot be fetched logs a warning and the run continues** with what it has. Amazon's
  block is transient and per-session, so re-running usually clears it; `diagnose: true` shows the raw bytes.
- **Long runs stop before the clock does.** The actor reads its own run timeout, reserves the tail for
  emitting, and pushes everything collected so far rather than being killed mid-crawl. If you see
  `Wall-clock budget reached`, raise the run timeout or lower `maxItems` / `maxPagesPerTerm`.
- **A dead ASIN returns 404 and is logged and skipped** (`product B0XXXXXXXX: 404 (delisted / invalid ASIN)`),
  not emitted as an empty billed row. You are never charged for an ASIN that no longer exists.
- **A product page that comes back but parses no title is dropped**, logged as
  `page returned but no title parsed` — a degraded row is worse than a missing one.
- **In the detail pass, products whose page never came back keep their search-listing data** and the run logs
  how many, e.g. `Enriched 38/40` plus a warning naming the 2.
- **`diagnose: true` writes `DIAGNOSE`, `DEBUG_SEARCH_PAGE_1`, `DEBUG_SEARCH_PAGE_2` and `DEBUG_PRODUCT` to
  the key-value store and exits without a dataset row** — so you can see the exact bytes Amazon sent us
  without paying for anything.

### Who buys this

- **Price-monitoring and repricing tools** — `asin` + `price` + `currency` + `availability` on a schedule is
  the entire input to a repricer; `priceRaw` keeps the audit trail.
- **Brand-protection and MAP-enforcement teams** — run your own brand terms and watch which `sponsored` ASINs
  and which `price` points show up against them.
- **Private-label sellers doing keyword research** — a keyword's full 308-ASIN walk with `rating` and
  `reviewCount` on every row is a saturation map: how many incumbents, at what price, with what review moat.
- **Retail-media and ad agencies** — `sponsored: true` on 9.7% and 17.4% of the same category walk on two
  different days is a live read on who is buying that keyword.
- **E-commerce catalogue and PIM teams** — `features` (median 5 bullets) and `images` (median ~20 hi-res URLs)
  populate a product record without a manual copy-paste.
- **Market researchers pricing a category** — `price` at 99.7% fill across a whole keyword gives a real price
  distribution rather than a top-10 sample.

### Related actors from us

| Actor | What it is | Why you would use it instead |
|---|---|---|
| `ScrapersDelight/shopgoodwill-scraper` | ShopGoodwill auctions by keyword, category or seller | Second-hand and auction pricing, with bids and end times, instead of new retail listings |
| `ScrapersDelight/hipstamp-scraper` | HipStamp collectibles listings | Collectibles inventory, where the marketplace is not Amazon |

And the honest one-liner: if you need Best Sellers Rank, sales estimates, offers or seller objects, this is not
the actor — buy the depth from a depth actor and use this one for cheap, wide, keyword-driven coverage.

### FAQ

**Does this need an Amazon account, a login or cookies?**
No. It reads public search-result and product pages only. There is no account, no cookie jar and no API key.

**How much does it cost to scrape 1,000 Amazon products?**
$4.50, at $0.0045 per product returned. There is no actor-start fee. Apify residential proxy traffic is billed
separately by the platform.

**Do I get charged for the extra product-page fetch when I turn on full detail?**
No. The price is $0.0045 per product either way. Full detail costs you wall-clock time — 40 products took
1 min 58 s with detail — not money.

**Can I get Amazon's whole catalogue in one run?**
No, and nobody can from search. A query bottoms out at ~7 useful pages: `running shoes` returned 308 unique
ASINs in total. Scale comes from running many keywords.

**Two runs, will I get duplicates?**
Within a run, no — products are deduplicated on ASIN before they are fetched or billed. Across runs, yes:
re-running the same keyword returns the same ASINs. Deduplicate on `asin` on your side.

**Does it need a proxy?**
Yes, residential. A single datacenter attempt cleared 2 of 20 requests; residential cleared 12 of 20, and
residential with the built-in fresh-session retry delivered 45 of 45 target pages. The default is already
correct — leave it.

**Can I scrape amazon.co.uk or amazon.de?**
Yes — set `domain` and change nothing else; the proxy exit country follows it automatically. That is
load-bearing: amazon.co.uk failed 6 of 6 attempts from a US exit, and amazon.de served a US exit its prices in
USD. amazon.com, .co.uk, .de and .ca are live-verified; the other eight share the same code path but have not
been individually measured.

**Why is `brand` empty on some rows?**
On search rows it depends which of Amazon's two card layouts you got — 93.5% on one, 0 of 22 on the other.
On full-detail rows it is 90–92.5% across two runs; the missing rows are ASINs with no byline on the product
page. Turn on `fetchProductDetails` if you need brand reliably.

**What does `price: null` mean?**
That Amazon showed no buyable price — normally "Currently unavailable". It was 1 row in 308 on the search
walk. It is an inventory state, not a scraping error.

**Does it return reviews, Q\&A, BSR or estimated sales?**
No. Review *counts* and star ratings, yes; review *text*, Q\&A, Best Sellers Rank, offers, sellers and sales
estimates, no. Those belong in a different actor and this page will not pretend otherwise.

**Will a run ever succeed with zero rows?**
No. A run that scrapes nothing throws with the reason rather than handing you a green tick and an empty
dataset.

**Something looks wrong — how do I debug it without paying?**
Set `diagnose: true`. It fetches two search pages and one product page, writes the raw HTML plus a parse
report to the key-value store, and exits without writing a dataset row, so nothing is charged.

**Can I run it on a schedule or from the API?**
Yes — Apify Schedules, the Apify API, MCP and the standard integrations (Make, Zapier, Google Sheets, Slack,
webhooks) all work, and output exports as JSON, CSV, Excel or HTML.

### Legal and fair use

This Actor reads publicly accessible Amazon search-result and product pages. It does not log in, does not
solve CAPTCHAs, does not use a CAPTCHA-solving service, and collects nothing behind any authentication.

Amazon's Terms of Service prohibit scraping and direct automated access to Amazon's paid Product Advertising
API. Technical access is not permission. Deciding whether your use is lawful in your jurisdiction, and
handling any data you collect in line with applicable law, is your responsibility as the operator. Product
listings can contain seller names and other personal data — if you process it, GDPR/CCPA obligations are
yours.

Amazon® is a trademark of Amazon.com, Inc. This Actor is not affiliated with, endorsed by or sponsored by
Amazon.

### Feedback

Found a missing field or want a new filter? Open an issue on the **Issues** tab.

# Actor input Schema

## `searchTerms` (type: `array`):

Keywords exactly as you would type them into the Amazon search box. Each term is paged through up to the page limit below. Measured 2026-08-13 on amazon.com: a results page carries 16–60 cards depending on the query and the day ('wireless earbuds' 16–22, 'running shoes' 60). Leave the prefilled term to try the actor as-is.

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

Paste a browser URL ('https://www.amazon.com/dp/B09B8V1LZ3', with or without the /ref= tail), a /gp/product/ URL, or a bare 10-character ASIN ('B09B8V1LZ3') — all three are accepted, one per line. Every entry here is fetched as a full product page and billed once, whatever the detail toggle says. Optional if you gave search terms.

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

Stop after this many unique products across all inputs. You are billed $0.0045 per product returned, so this is your hard cost ceiling: 20 = $0.09, 1,000 = $4.50. Duplicate ASINs are dropped before billing and never count against it. Set 0 for no cap (bounded only by pages-per-term).

## `maxPagesPerTerm` (type: `integer`):

How many search-result pages to walk for each term. Amazon serves at most ~7 pages per query and then repeats itself, so values above that buy nothing. Measured on a contiguous 5-page walk (2026-08-13): 300 raw cards for 'running shoes' collapsed to 248 unique ASINs — the repeats cost you time, not money.

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

Keep Amazon's ad placements (they arrive flagged `sponsored: true`). Measured 2026-08-13: 11 of 75 unique products (14.7%) on a 5-page 'wireless earbuds' walk were sponsored. Turn this off for organic results only — dropped cards are never charged.

## `fetchProductDetails` (type: `boolean`):

Opens each search result's own product page to add brand, availability, in-stock flag, feature bullets and the full hi-res gallery. Costs one extra request per product and roughly triples run time — but NOT one extra charge: the price is $0.0045 per product either way. Measured on two independent 40-product runs (2026-08-13): brand 90% and 92.5%, availability 100% and 97.5%, features 100% both (median 5 bullets), images 100% both (median 20-21 images).

## `domain` (type: `string`):

Which Amazon marketplace to scrape. The proxy exit country follows this automatically — amazon.co.uk exhausted 6 of 6 attempts from a US exit and cleared in 2 from a GB one, and amazon.de served USD prices in English to a US exit, so this is load-bearing. Prices are labelled from the marketplace's own currency ($ on amazon.ca is CAD, not USD).

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

Residential is REQUIRED. Measured through Apify on 2026-08-13, single attempt, N=20 per rung: Apify datacenter (auto) cleared 2/20 = 10%; Apify RESIDENTIAL cleared 12/20 = 60%; RESIDENTIAL plus the built-in brand-new-session retry delivered 45 of 45 target pages = 100%. Leave this alone. If you do pin a country here it overrides the marketplace default, which is usually a mistake.

## `requestConcurrency` (type: `integer`):

Parallel product-page requests during the detail pass. Values above 6 are clamped: Amazon tightens its block rate under burst load, and a higher setting buys retries, not speed. 4 is the tested setting.

## `diagnose` (type: `boolean`):

Fetch two search pages plus one product page, dump the raw HTML to the key-value store (DEBUG\_SEARCH\_PAGE\_1/2, DEBUG\_PRODUCT) with a DIAGNOSE report of card counts, parsed fill and how many ASINs page 2 repeats from page 1 — then exit without writing a single dataset row, so nothing is charged. Use this before opening an issue.

## Actor input object example

```json
{
  "searchTerms": [
    "wireless earbuds",
    "yoga mat"
  ],
  "productUrls": [
    "https://www.amazon.com/dp/B09B8V1LZ3",
    "B0BQPNMXQV"
  ],
  "maxItems": 100,
  "maxPagesPerTerm": 5,
  "includeSponsored": true,
  "fetchProductDetails": false,
  "domain": "amazon.co.uk",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "requestConcurrency": 4,
  "diagnose": false
}
```

# Actor output Schema

## `products` (type: `string`):

ASIN, URL, title, brand, price, currency, rating, review count, availability, in-stock flag, sponsored flag, feature bullets and gallery images.

# 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 = {
    "searchTerms": [
        "wireless earbuds"
    ],
    "maxItems": 20,
    "fetchProductDetails": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapersdelight/amazon-product-scraper").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 = {
    "searchTerms": ["wireless earbuds"],
    "maxItems": 20,
    "fetchProductDetails": False,
}

# Run the Actor and wait for it to finish
run = client.actor("scrapersdelight/amazon-product-scraper").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 '{
  "searchTerms": [
    "wireless earbuds"
  ],
  "maxItems": 20,
  "fetchProductDetails": false
}' |
apify call scrapersdelight/amazon-product-scraper --silent --output-dataset

```

## MCP server setup

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

```

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/1AM8FHC0sxDdDjTef/builds/rSOk9O0hfDrkF3drY/openapi.json
