# Amazon Product Scraper 🛒 (bulk keyword & ASIN export) (`tagadanar/amazon-product-scraper`) Actor

Pull an Amazon catalogue in bulk: give it keywords, ASINs or product links and get a flat row per product with price, list price, discount, rating, review count, image, badges and rank position. Optionally opens each product page for brand, Best Sellers Rank, stock and seller.

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

## Pricing

from $0.70 / 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 Product Scraper 🛒

Give it keywords, ASINs or product links and get an Amazon catalogue back as a
flat table: price, list price, discount, rating, review count, image, badges,
delivery wording, sponsored flag and the rank position each product held for the
keyword that found it. No API key, no browser, no proxy to configure, and you
pay $1 per 1,000 products.

It is built for the bulk pull. If what you actually want is to watch a handful of
listings over time (who holds the Buy Box today, did the price move since
yesterday, is this "German" seller really a company in Shenzhen), that is a
different job and a different actor: see
[Amazon Buy Box & Price Monitor](https://apify.com/tagadanar/amazon-product-monitor).

### What you get

One row per product. Fields marked "product page" are filled when you turn on
"Open each product page for the full record", and always for ASINs and links you
give directly.

| field | example | notes |
| --- | --- | --- |
| `asin` | `B004YAVF8I` | |
| `title` | `Logitech M185 Compact Ambidextrous Wireless Mouse…` | |
| `url` | `https://www.amazon.com/dp/B004YAVF8I` | clean link, no tracking blob |
| `price` / `currency` / `priceText` | `12.79` / `USD` / `$12.79` | `null` when Amazon shows no offer |
| `listPrice` / `discountPercent` | `15.45` / `17` | the strikethrough price and the discount off it |
| `rating` / `reviewCount` | `4.5` / `44754` | |
| `boughtInPastMonth` | `10K+ bought in past month` | Amazon prints this on popular listings only |
| `image` | `https://m.media-amazon.com/images/I/…jpg` | |
| `badges` | `["Best Seller", "Amazon's Choice"]` | also Climate Pledge Friendly, New Arrival, Limited time deal |
| `couponText` | `Save 15%` | when a clippable coupon is shown |
| `delivery` | `FREE delivery Wed, Sep 9` | as worded for the region the run exits from |
| `availability` | `Only 17 left in stock - order soon.` | |
| `isPrime` | `true` | |
| `sponsored` | `false` | ad slots are labelled, never hidden |
| `searchQuery` / `page` / `position` | `wireless mouse` / `1` / `2` | rank position for that keyword |
| `brand` | `Logitech` | product page |
| `bsr` / `bsrCategory` | `1` / `Computer Mice` | product page, Best Sellers Rank |
| `inStock` | `true` | product page |
| `seller` | `{name, id, isAmazon, fulfilledBy}` | product page |
| `features` | `["Compact Mouse: …", …]` | product page, the About this item bullets |
| `images` | `[…]` | product page, up to 12 gallery images |
| `status` | `ok` | anything other than `ok` was delivered free of charge |

Amazon sites covered: amazon.com, amazon.co.uk, amazon.de, amazon.fr,
amazon.it, amazon.es.

### Who uses it

**Price and assortment monitoring.** Pull a category every morning, diff it
against yesterday's dataset, and you have price moves, new entrants and stock-outs
across a whole keyword set. `listPrice` and `discountPercent` come from the same
card, so a promotion is visible without a second request.

**Product research and sourcing.** Rating, review count and
`boughtInPastMonth` on the same row let you sort a keyword's first pages by
demand rather than by whatever Amazon decided to rank today. Turn on the product
page pass and you also get Best Sellers Rank and the brand.

**Keyword and rank tracking.** Every row carries the keyword, the page and the
position it held, plus whether the slot was paid. Run the same keyword list on a
schedule and you have organic and sponsored share of the first pages over time.

**Competitor and reseller watching.** Give a list of ASINs, get the product page
record for each, including who is selling it and who fulfils it.

**Feeding other actors.** The dataset is flat, so it pipes straight into
[Amazon Buy Box & Price Monitor](https://apify.com/tagadanar/amazon-product-monitor)
for the ASINs worth watching closely, or into
[Marketplace Arbitrage Score](https://apify.com/tagadanar/marketplace-arbitrage-score)
against another marketplace's prices.

### Input examples

Bulk keyword pull, five pages per keyword:

```json
{
  "searchKeywords": ["wireless mouse", "usb c hub", "mechanical keyboard"],
  "domain": "com",
  "maxPagesPerKeyword": 5,
  "maxItems": 500
}
```

A known ASIN list, full product records:

```json
{
  "asins": ["B00PGB7OKM", "B004YAVF8I", "B0BXNR9DB6"],
  "domain": "com"
}
```

Keywords on amazon.de with the product page opened for every hit:

```json
{
  "searchKeywords": ["kabellose maus"],
  "domain": "de",
  "maxPagesPerKeyword": 3,
  "maxItems": 100,
  "fetchProductDetails": true
}
```

Products from two Amazon sites in one run (links keep their own site):

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

### Pricing

Pay per event, and you pay for results, not for attempts.

| event | price per 1,000 | what it covers |
| --- | --- | --- |
| Product scraped | **$1.00** | one product from a keyword search, with everything the result card carries |
| Product page read | **$2.50** | one product page opened and merged in, charged only when the page actually returned an offer |
| Actor start | $0.001 per run | |

Bronze, Silver and Gold plans get 10%, 20% and 30% off, so the product event is
$0.70 per 1,000 on Gold. Platform usage (compute) is on us and there is nothing
else to pay: proxies, when a run needs them, are included in that price and there
is no proxy setting for you to configure or fund.

Four things are deliberately free:

- products that a wall or an unreadable page stopped us from getting. You get a
  row saying so, at no charge.
- pages where Amazon served its cached, price-less copy. Those rows carry
  `status: "price-withheld"` and cost nothing, because a product row with no
  price is not the thing you bought.
- product pages skipped because Amazon pushed the run onto a metered route. A
  product page is roughly forty times the size of a search result card, and past
  a point it costs us more to fetch than this actor charges for it. Rather than
  quietly pricing that risk into everyone's bill, the run stops opening product
  pages, marks the affected rows `status: "not-fetched"` and tells you in the
  run summary. Search results are unaffected, and re-running later usually
  clears it.
- product pages that came back without an offer at all.

### FAQ

**How deep can it go on one keyword?**
Twenty result pages. That is Amazon's own limit, not ours: it advertises tens of
thousands of results for a broad keyword and then stops paginating at page 20,
after which it keeps answering with a page of filler that looks perfectly
healthy. This actor stops at the real last page and says so in the run status,
rather than billing you for the filler. Depending on the keyword and the layout
Amazon picks, a page holds roughly 16 to 48 products, so plan on a few hundred
per keyword. For deeper coverage, split the keyword (brand, model, colour) the
way a shopper would.

**Do I need a proxy, or an Amazon API key?**
No, and there is nothing to configure. The actor picks its own route to Amazon,
starting with the cheapest one that works and moving up only if Amazon refuses
it. That decision is made fresh on every run, and the run summary tells you
which route it ended up using. Platform usage is on us either way, so this never
becomes your bill.

**What happens when Amazon refuses a request?**
Amazon's HTTP 503 is a throttle, not a ban, so every refused request is retried
on both TLS fingerprints with fresh cookies and a 5s, 20s then 45s backoff
before the actor accepts the refusal. If all four attempts are refused, the run
says so: the status message starts with "Blocked by Amazon" and names the
fingerprints and the status codes it got. You are never told "no results" when
what really happened is that we were turned away, and nothing from a refused
page is charged.

**And when a keyword genuinely has no matches?**
You get a run that says so and names its evidence: Amazon's own result count for
the keyword was zero. Worth knowing, because Amazon renders a handful of
unrelated "you might also like" cards on that page; those are suggestions, not
matches, and this actor does not ship them as results for your keyword.

**Why is a price sometimes null?**
Two different reasons and the row tells you which. A single card with no price on
an otherwise normal page is a listing Amazon is showing without an offer (variant
only, "See options"). A whole page with no prices anywhere is Amazon serving its
cached copy, which it does per TLS fingerprint; the actor retries on a second
fingerprint automatically and, if that fails too, ships the rows free with
`status: "price-withheld"`.

**Can I get prices in USD when I run amazon.com from Europe?**
Amazon decides the currency and the delivery wording from where the request comes
out, not from the site you asked for. `currency` always says what was actually
shown, and `priceText` keeps the original string.

**Does it return sponsored products?**
Yes, flagged with `sponsored: true`, which is what makes ad-share tracking
possible. Filter them out in your dataset view if you only want organic results.

**What is the difference with Amazon Buy Box & Price Monitor?**
This one is the bulk extractor: many keywords, many products, one flat export.
The monitor is the watch: a short ASIN list, the live Buy Box winner and how it
fulfils, a change record when price, seller or stock moves between runs, and on
EU sites a check of the seller's published legal identity against the official
VAT and company registers.

**Is scraping Amazon search results legal?**
This actor reads pages Amazon publishes to anyone, with no login, and it collects
no personal data. As always, check the terms that apply to your own use.

***

Amazon scraper, Amazon product scraper, Amazon search scraper, Amazon price
scraper, Amazon keyword rank tracker, Amazon ASIN lookup, Amazon product data
export, amazon.de scraper, amazon.co.uk scraper, Amazon bulk product extractor,
Amazon Best Sellers Rank, Amazon competitor price monitoring, Jungle Scout
alternative, Amazon crawler alternative.

# Actor input Schema

## `searchKeywords` (type: `array`):

One keyword per line, exactly what you would type into Amazon's search box, e.g. <code>wireless mouse</code>. Every result page is read and you get one row per product: price, list price, rating, review count, image, badges, delivery wording and the rank position it held for that keyword.

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

Products you already know, one ASIN per line, e.g. <code>B00PGB7OKM</code>. They are read on the Amazon site chosen below, straight from the product page, so they come back with brand, Best Sellers Rank, stock wording, the seller and the image gallery.

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

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

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

Which Amazon site the keywords and ASINs are read on. Product links override this per link.

## `maxPagesPerKeyword` (type: `integer`):

How deep to go for each keyword. Amazon itself stops paginating a keyword at 20 pages however many results it advertises, so 20 is the maximum and the actor stops at whatever Amazon actually offers, which is usually less.

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

Stop the whole run after this many products. You are only charged for products actually delivered.

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

Search cards do not carry brand, Best Sellers Rank, stock wording, the seller or the image gallery. Turn this on and every search hit also gets its product page read and merged into the same row. It makes the run slower and is billed separately, per product page that actually returned an offer. ASINs and product links you give directly always go through the product page, whether this is on or off.

## Actor input object example

```json
{
  "searchKeywords": [
    "wireless mouse"
  ],
  "asins": [
    "B00PGB7OKM"
  ],
  "domain": "com",
  "maxPagesPerKeyword": 1,
  "maxItems": 20,
  "fetchProductDetails": false
}
```

# Actor output Schema

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

One row per product 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 = {
    "searchKeywords": [
        "wireless mouse"
    ],
    "asins": [
        "B00PGB7OKM"
    ],
    "maxPagesPerKeyword": 1,
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("tagadanar/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 = {
    "searchKeywords": ["wireless mouse"],
    "asins": ["B00PGB7OKM"],
    "maxPagesPerKeyword": 1,
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("tagadanar/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 '{
  "searchKeywords": [
    "wireless mouse"
  ],
  "asins": [
    "B00PGB7OKM"
  ],
  "maxPagesPerKeyword": 1,
  "maxItems": 20
}' |
apify call tagadanar/amazon-product-scraper --silent --output-dataset

```

## MCP server setup

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