# Amazon Bestsellers Scraper (`s-r/amazon-bestsellers`) Actor

- **URL**: https://apify.com/s-r/amazon-bestsellers.md
- **Developed by:** [SR](https://apify.com/s-r) (community)
- **Categories:** E-commerce, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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 Bestsellers Scraper

An Amazon bestsellers scraper that returns a ranked product list from any Amazon category, on any of 15 marketplaces, with the price in that marketplace's own currency. Give it a category and it returns Amazon's own rank badge alongside the ASIN, title, price, star rating and rating count.

No login, no cookie, no captcha solve. Amazon renders its ranking pages server-side for logged-out visitors, which is the surface this actor reads.

### What you get

- **Amazon's real rank**, taken from the rank badge on the page, not renumbered by row order. When Amazon skips ranks, you see the skip instead of a tidy fiction
- **Price in the correct currency**, because the proxy exit is pinned to the marketplace's own country. This matters more than it sounds: an unpinned request to amazon.com came back priced in Egyptian pounds
- **15 marketplaces** on one input: US, UK, Germany, France, Italy, Spain, Netherlands, Sweden, Poland, Canada, Australia, Mexico, Brazil, India and Japan
- **Three rankings** from the same actor: Best Sellers, New Releases, and Movers & Shakers
- **Rating and rating count per product**, so you can separate a bestseller with 280.000 ratings from one that climbed on 40
- **A useful error when you point it at a hub page.** Amazon's top-level category pages render in the browser and carry no products in the HTML. Instead of returning zero rows and letting you guess, the actor names the problem and tells you to use a leaf category
- **No actor-start fee.** A run that returns nothing costs nothing

### Why scrape Amazon bestsellers

The bestseller rank is the closest thing Amazon publishes to a sales figure. Amazon will not tell you units sold, but it will tell you, hourly, which products outsell which in every category on every marketplace. For anyone deciding what to stock, what to launch, or what a competitor is winning with, that ranking is the primary signal and there is no API for it.

The second reason is drift. A ranking is only interesting as a series. Yesterday's number one that is now at 14 tells you something the snapshot never will, and the only way to build that series is to capture it on a schedule. This actor is built for that: small runs, cheap per row, no start fee eating the budget of a job you run every hour.

Currency is where most Amazon scrapers quietly break. Amazon prices off the requesting IP, so a scraper running through a rotating proxy without country pinning returns prices in whatever country the exit landed in that minute. The rows look fine. The numbers are unusable. This actor pins the exit to the marketplace before the request goes out.

### Input

| Field | Type | Required | Default | What it does |
|---|---|---|---|---|
| `category` | string | yes | `electronics` | Category slug, numeric node id, or a full Amazon ranking URL |
| `marketplace` | select | no | `com` | Which Amazon site, and therefore which currency and proxy exit country |
| `list_type` | select | no | `bestsellers` | `bestsellers`, `new_releases` or `movers_and_shakers` |
| `limit` | integer | no | `30` | Products to return, 1 to 60 |
| `retries` | integer | no | `4` | Retry attempts per page, each with a rotated user agent and TLS fingerprint |

### Output

```json
{
  "rank": 1,
  "asin": "B08JHCVHTY",
  "title": "Blink Plus Plan with monthly auto-renewal",
  "url": "https://www.amazon.com/Blink-Plus-Plan-monthly-auto-renewal/dp/B08JHCVHTY",
  "price": 11.99,
  "price_text": "$11.99",
  "currency": "$",
  "rating": 4.4,
  "rating_text": "4.4 out of 5 stars",
  "reviews_count": 279727,
  "image": "https://images-na.ssl-images-amazon.com/images/I/...",
  "marketplace": "com",
  "category": "electronics",
  "list_type": "bestsellers"
}
```

### Use cases

**Deciding what to stock.** Pull the top of a category on the marketplaces you sell in, then join on ASIN against your own catalogue. What is ranked and absent from your range is the gap, and the rating count tells you whether it is a genuine seller or a recent spike. Run it across `com`, `co.uk` and `de` and you get the same question answered per market in one afternoon.

**Tracking a launch.** New Releases is the list that matters when a competitor ships something. Schedule it hourly on their category with `list_type: new_releases`, deduplicate on ASIN, and you know within the hour when something new enters the ranking, at what price and with how many early ratings.

**Building a rank time series.** The single most valuable thing here is the same run repeated. Store `rank`, `asin` and the timestamp, and after a fortnight you have a movement chart Amazon does not sell. Movers & Shakers gives you the same signal pre-computed for the last 24 hours when you want the answer without the history.

**Pricing research across borders.** The same ASIN often carries a very different price on amazon.de than on amazon.co.uk. Because the exit country is pinned per marketplace, running the same category across several marketplaces gives you comparable numbers rather than a currency soup.

### How it compares

| | this actor | `junglee/amazon-bestsellers` | `crawlerbros/amazon-bestseller-scraper` |
|---|---|---|---|
| Per 1.000 products | **$3,00** | $5,90 | $5,00 |
| Actor-start fee | **none** | none | $0,05 per run |
| Run failure rate | 0% across validation runs | **10,9%** over 30 days | – |
| Marketplaces | **15** | fewer | fewer |
| New Releases and Movers & Shakers | **yes, same input** | separate actors | no |
| Currency pinned to marketplace | **yes** | not stated | not stated |
| Rating and rating count | **yes** | yes | yes |

Honest about the other side: `junglee/amazon-bestsellers` has 331 monthly users and 11 reviews against our zero, and it has been running for years. The reason to switch is that it fails one run in nine and costs twice as much, not that it cannot do the job.

### Pricing

One event. `product` costs $0,0030 per ranked product returned, which is $3,00 per 1.000. All pricing is pay-per-event, so you only pay for products you actually receive. No actor-start fee, no per-compute-unit charges, and a run that returns nothing costs nothing.

### Limits and gotchas

- **60 products is the real ceiling per run, and the ranks have a gap.** Amazon's `pg` parameter steps by 50 but only 30 of each page's ranks are in the HTML. You get ranks 1-30 and 51-80. Ranks 31-50 and 81-100 are loaded in the browser and are not available to any HTML scraper, so an actor claiming a clean top 100 is either renumbering rows or using a browser.
- **Use a leaf category, not a hub.** `gp/bestsellers/ce` on amazon.de is a hub page and returns no products. `gp/bestsellers/ce/562066` returns 30. The actor detects this and tells you, rather than reporting an empty run.
- **Category slugs are not portable between marketplaces.** `electronics` works on `com`, `co.uk` and `fr`; on `de` the equivalent is `ce`. When in doubt, open the ranking in your browser and paste the URL into `category`.
- **Books rankings carry fewer fields.** Amazon does not render a star rating on book tiles in every marketplace, so `rating` and `reviews_count` can be empty there while price and rank are present.
- **Prices reflect the pinned exit country**, which is what you want, but it means a marketplace you cannot reach from that country will behave oddly. All 15 listed marketplaces were checked.
- **Movers & Shakers is only meaningful hourly.** It is a 24-hour delta list, so running it daily gives you a snapshot of a window you have already missed most of.

### FAQ

**Can I scrape Amazon bestsellers without an API key?**
Yes. Amazon publishes its ranking pages to logged-out visitors and search engines, and that is the surface this actor reads. There is no credential field in the input.

**Why does my Amazon scraper return prices in the wrong currency?**
Because Amazon prices off the requesting IP and most rotating proxies pick a random exit country per request. This actor pins the exit to the marketplace's country before the request goes out, which is why `amazon.de` returns euros rather than whatever the proxy landed in.

**Can I get the full Amazon top 100?**
Not from the HTML. Amazon renders 30 ranks per 50-rank page, so ranks 31-50 and 81-100 exist only after the browser loads them. This actor returns the 60 that are really there and tells you which ranks they are.

**Which Amazon marketplaces are supported?**
Fifteen: com, co.uk, de, fr, it, es, nl, se, pl, ca, com.au, com.mx, com.br, in and co.jp. Each one is fetched through an exit in its own country.

**How do I find the category id for a marketplace?**
Open the ranking you want in a browser and copy the URL. Both the slug form and the numeric node id work, and you can paste the whole URL into `category` if you would rather not pick it apart.

### Related Actors

- [Google Shopping Scraper](https://apify.com/s-r/free-google-shopping-scraper---extract-offers-from-any-ean-sku) — offers from every merchant for an EAN or SKU
- [EAN to ASIN Converter](https://apify.com/s-r/free-ean-to-asin-converter---turn-any-ean-into-an-amazon-asin) — turn a barcode into an Amazon ASIN
- [Google Shopping Reviews](https://apify.com/s-r/free-google-shopping-reviews) — product reviews aggregated across merchants

# Actor input Schema

## `category` (type: `string`):

Category slug, numeric node id, or a full Amazon ranking URL. Must be a leaf category: a hub page such as 'ce' on amazon.de renders its products in the browser and carries none in the HTML. Use 'ce/562066' or paste the URL from your address bar.

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

Which Amazon site to read. The proxy exit is pinned to this country, so prices come back in the local currency rather than whatever country the proxy happened to land in.

## `list_type` (type: `string`):

Which ranking to read.

## `limit` (type: `integer`):

How many products to return, 1 to 60. Amazon server-renders 30 of each 50-rank page, so 60 is the real ceiling and the returned ranks are 1-30 and 51-80.

## `retries` (type: `integer`):

Retry attempts per page, each with a rotated user agent and TLS fingerprint.

## Actor input object example

```json
{
  "category": "electronics",
  "marketplace": "com",
  "list_type": "bestsellers",
  "limit": 30,
  "retries": 4
}
```

# Actor output Schema

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

One row per product, carrying Amazon's own rank.

## `summary` (type: `string`):

itemCount, errorCount, rankRange and the rank-gap note.

## `errors` (type: `string`):

Per-page failures with a code and a redacted message. Absent when the run had none.

# 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 = {
    "category": "electronics",
    "limit": 30,
    "retries": 4
};

// Run the Actor and wait for it to finish
const run = await client.actor("s-r/amazon-bestsellers").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 = {
    "category": "electronics",
    "limit": 30,
    "retries": 4,
}

# Run the Actor and wait for it to finish
run = client.actor("s-r/amazon-bestsellers").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 '{
  "category": "electronics",
  "limit": 30,
  "retries": 4
}' |
apify call s-r/amazon-bestsellers --silent --output-dataset

```

## MCP server setup

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

```

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/DdVrGEDTvYibteuua/builds/vaWWd7Q0Qk5ElBah5/openapi.json
