# Amazon Bestsellers Scraper (7 marketplaces) (`usestring/amazon-bestsellers`) Actor

Reads Amazon Best Sellers ranking pages and returns one row per ranked product: rank, ASIN, title, displayed price, star rating and review count. You give it category slugs rather than ASINs, and every marketplace picked is crossed with every category. Covers US, UK, DE, FR, ES, JP and AU.

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

## Pricing

from $1.75 / 1,000 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

### What does Amazon Bestsellers Scraper do?

It reads Amazon's public Best Sellers ranking pages and returns one row per ranked product, with the
position Amazon itself printed on the page. The input is a list of **category slugs and
marketplaces**, not a list of products: you say which shelves to read, and the run comes back with
what is selling on them right now. That is what separates it from its two siblings — [Amazon Product
Scraper](https://apify.com/usestring/amazon-products) answers a question about an ASIN you already
have, [Amazon Search Scraper](https://apify.com/usestring/amazon-search) answers a keyword, and this
one answers "what is at the top of this category today".

- Every marketplace you pick is crossed with every category you pick, so three marketplaces and two
  categories is six pages and roughly 180 rows from one run.
- Seven storefronts are available together — US, UK, Germany, France, Spain, Japan and Australia —
  and each row carries the `marketplace` it came from.
- `rank` is Amazon's own badge number read off the page, so it survives sorting, filtering and
  joining. It is not the order rows happened to arrive in.
- Every row carries an `asin`, which joins straight onto the Amazon Product Scraper for the full
  detail record.
- A category slug that does not exist on a given marketplace fails only that one target. The rest of
  the run still returns.

No Amazon account, API key or cookies are involved. The Actor reads the Best Sellers page a
logged-out visitor sees, at about 30 products per category page and a median of 2.7 seconds per page
in our own measurements.

### What data does it extract?

| Field | Type | Description |
| --- | --- | --- |
| `marketplace` | string | Which storefront the row came from: `us`, `uk`, `de`, `fr`, `es`, `jp` or `au` |
| `category` | string | The category slug that was requested, echoed back on every row |
| `rank` | number | Bestseller position from the page's own rank badge, 1-based |
| `asin` | string | Amazon's ten-character product ID. Stable, and the right key to join or de-duplicate on |
| `title` | string | Product title, HTML entities decoded (`Tom &amp; Jerry` arrives as `Tom & Jerry`) |
| `price` | string | The price exactly as the ranking page displayed it, symbol and grouping included |
| `rating` | number | Stars out of 5. A locale decimal comma is read as a decimal point, so `4,4` on amazon.de is `4.4` and not `44` |
| `reviewCount` | number | Review total as an integer: `278974`, not `"278,974"` |
| `productUrl` | string | Direct `/dp/` link on the marketplace the row came from |
| `sourceUrl` | string | The Best Sellers page the row was read from |
| `collectedAt` | string | ISO timestamp stamped once per run |

Rows that carry neither an ASIN nor a title are dropped rather than emitted half-empty, so a
malformed tile in the grid costs you that tile and nothing else.

`price` is a string here, and deliberately so. Unlike the product and search Actors, this one does
not pin the exit country per marketplace, so treat the value as the display string the page printed
rather than as a currency-tagged number. When you need a numeric price with an ISO currency beside
it, take the `asin` from these rows and run it through the Amazon Product Scraper.

### Why scrape Amazon Best Sellers?

- **Rank tracking.** Run the same categories daily and you have a time series of who moved up, who
  fell off the page, and what price they were charging while it happened.
- **Launch detection.** A new ASIN appearing in a category's top 30 is one of the earliest public
  signals that a competitor's product is working.
- **Cross-country assortment.** The same category slug on `us`, `de` and `jp` shows which products
  travel and which are local. This is the reason the marketplace list is an array rather than a
  single choice.
- **Sourcing and niche research.** Rating and review count on every row give you a rough demand
  floor for a category before you commit to stock.
- **Merchandising and pricing dashboards.** Schedule the run, point a dashboard at the dataset, and
  the rank ladder for your categories refreshes itself.

### How to use it

1. Open the Actor and click **Try for free** (or **Start** if you are already signed in).
2. Fill in **Categories** with one or more slugs. The slug is the path segment in a Best Sellers
   URL: `amazon.com/gp/bestsellers/electronics/` is `electronics`, and `toys-and-games` and `books`
   work the same way.
3. Tick the **Marketplaces** you want. Each one is fetched for each category.
4. Set **Maximum results** if you want a hard ceiling on the dataset, and raise **Concurrency** if
   you are collecting many combinations at once.
5. Run it. When it finishes, check the `SUMMARY` record in the run's key-value store for the item
   count and for any target that failed, then export the dataset as JSON, CSV, Excel or XML, or read
   it through the API.

### Input

| Field | Type | Default | Notes |
| --- | --- | --- | --- |
| `marketplaces` | array of strings | `["us"]` | Any of `us`, `uk`, `de`, `fr`, `es`, `jp`, `au`. At least one is required |
| `categories` | array of strings | `["electronics"]` | Bestseller category slugs, 1 to 50 of them. Letters, digits and hyphens only |
| `maxItems` | integer | `1000` | Ceiling on dataset rows, 1 to 50,000 |
| `concurrency` | integer | `3` | Pages fetched in parallel, 1 to 10 |

```json
{
  "marketplaces": ["us", "uk", "de"],
  "categories": ["books", "electronics"],
  "maxItems": 1000,
  "concurrency": 3
}
```

**Category slugs are marketplace-specific.** `books` resolves on all seven storefronts;
`electronics` is a valid slug on amazon.com but not on amazon.de, where the equivalent shelf is
`computers`. An unknown slug fails that single target with a message saying the slug may not exist
there, and every other target in the run still returns its rows.

Duplicates in either list are collapsed before any fetching happens, so the same category listed
twice costs one page, not two.

### Output

One row per ranked product. This is the shape rather than a captured run:

```json
[
  {
    "marketplace": "us",
    "category": "electronics",
    "rank": 1,
    "asin": "B08JHCVHTY",
    "title": "Blink Plus Plan (Monthly Subscription)",
    "price": "$11.99",
    "rating": 4.4,
    "reviewCount": 278974,
    "productUrl": "https://www.amazon.com/dp/B08JHCVHTY",
    "sourceUrl": "https://www.amazon.com/gp/bestsellers/electronics/",
    "collectedAt": "2026-08-20T09:14:02.881Z"
  },
  {
    "marketplace": "de",
    "category": "computers",
    "rank": 2,
    "asin": "B0BDHWDR12",
    "title": "SanDisk Ultra microSDXC 128 GB",
    "price": "12,99 €",
    "rating": 4.7,
    "reviewCount": 41230,
    "productUrl": "https://www.amazon.de/dp/B0BDHWDR12",
    "sourceUrl": "https://www.amazon.de/gp/bestsellers/computers/",
    "collectedAt": "2026-08-20T09:14:02.881Z"
  }
]
```

### Reliability

Measured across 21 marketplace-by-category combinations in a single run: 20 of 21 targets
succeeded and 600 products were collected, with every schema field populated. The one failure was a
category slug that does not exist on that marketplace, and it was reported as exactly that.

Ranks, prices, ratings and counts are parsed from the Best Sellers grid itself, so they are the
page's own values rather than a language model's reading of them. The one place that shows is the
rating line, which is localized: the parser knows the English, German, French and Spanish wordings
of "out of 5 stars". Where a storefront prints it in some other form, the row still carries rank,
ASIN, title and price, with `rating` left null instead of guessed at.

### How much does it cost?

Pricing is pay-per-event: you are charged per result row written to the dataset, and nothing else.
Rows are only written when they can be charged, so a run that hits your account spend limit stops
writing rather than quietly handing you unbilled data. Current per-row pricing is on the Actor's
Store page, which is the only place it can go stale.

Runs started from an Apify **free plan** stop at **250 requests and 250 results**, and the run
reports that it reached the limit in its status message. Any paid plan runs the full input and the
`maxItems` you set.

That limit exists because this Actor fetches through our own scraping infrastructure, which Apify
does not cover for free-plan runs. It binds on requests as well as results, so a long input list
cannot spend those fetches on rows the run was never going to return.

### Using it with the Apify API

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

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });

const run = await client.actor('usestring/amazon-bestsellers').call({
  marketplaces: ['us', 'de'],
  categories: ['books'],
  maxItems: 500
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.slice(0, 3));
```

The same run is reachable from the Python client, from any HTTP client against the Apify REST API,
and from a schedule if you want the ranking snapshot taken for you every morning.

### Limitations

Ranking pages only. There is no product description, image set, variant matrix, seller list, review
text or Q\&A here — the Amazon Product Scraper covers the detail page, and the Amazon Search Scraper
covers keyword results. The Actor reads the first ranking page of a category and does not paginate
into the rest of the top 100. `price` is a display string rather than a normalized number.
Marketplaces beyond the seven listed above, amazon.in included, are not supported.

### Related actors

- [Amazon Product Scraper](https://apify.com/usestring/amazon-products) — feed it the ASINs from
  these rows for numeric prices, currency, availability and brand.
- [Amazon Search Scraper](https://apify.com/usestring/amazon-search) — keyword results with ranks and
  a sponsored flag, for the demand you cannot see from a category page.
- [Walmart Product Scraper](https://apify.com/usestring/walmart-products) — the same product research
  on Walmart's catalogue, including marketplace sellers.
- [Home Depot Product Scraper](https://apify.com/usestring/homedepot-products) — price and stock for
  home-improvement SKUs, resolvable per store.
- [Etsy Listings Scraper](https://apify.com/usestring/etsy-listings) — handmade and vintage listings,
  useful when a category's competition sits outside the big-box marketplaces.

### FAQ

**How many products does one category return?**
About 30, which is one Amazon Best Sellers page. The Actor does not follow the pagination into the
rest of the top 100, so a category is one fetch.

**How do I find the right category slug?**
Open the Best Sellers page you care about on the marketplace you care about and copy the segment
after `/gp/bestsellers/`. Slugs are per-storefront, so check them on each one rather than assuming
the US slug carries over.

**Which marketplaces can it collect?**
Seven: US, UK, Germany, France, Spain, Japan and Australia, all in one run. amazon.in is
deliberately not offered.

**Is the price in local currency?**
It is whatever the ranking page printed, which is normally the storefront's own currency. This Actor
does not pin an exit country per marketplace, so if you need a guaranteed local numeric price take
the ASIN over to the Amazon Product Scraper, which does.

**How fresh is the data?**
It is the page as it stood when the run fetched it, stamped in `collectedAt` on every row. Amazon
recalculates Best Sellers hourly, so schedule the run at whatever interval your analysis actually
needs.

**What happens when a target fails?**
The failure is recorded under `failures` in the run's `SUMMARY` record with the URL and the reason,
and the other targets still write their rows. A run in which every single target failed exits as a
failed run rather than as an empty success.

**Do I need proxies or an anti-bot setup?**
No. Fetching goes through our own infrastructure and there is nothing to configure — no proxy
groups, no session pool, no retry policy to tune.

### Feedback

Something wrong, or a field you need that is not here? Open an issue from the Actor's Store page.
Bug reports that name the exact marketplace and category slug get fixed fastest.

# Actor input Schema

## `marketplaces` (type: `array`):

Amazon marketplaces to collect from.

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

Bestseller category slugs, e.g. electronics, books, toys-and-games.

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

Global cap on dataset items. Runs started from an Apify free plan stop at 250 requests and 250 results; any paid plan runs the full amount.

## `concurrency` (type: `integer`):

Targets fetched in parallel.

## Actor input object example

```json
{
  "marketplaces": [
    "us",
    "uk",
    "de"
  ],
  "categories": [
    "electronics"
  ],
  "maxItems": 1000,
  "concurrency": 3
}
```

# Actor output Schema

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

Reads Amazon Best Sellers ranking pages and returns one row per ranked product: rank, ASIN, title, displayed price, star rating and review count. You give it category slugs rather than ASINs, and every marketplace picked is crossed with every category. Covers US, UK, DE, FR, ES, JP and AU.

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

Item count, failure count and every target that failed, with its error.

# 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 = {
    "marketplaces": [
        "us",
        "uk",
        "de"
    ],
    "categories": [
        "electronics"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("usestring/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 = {
    "marketplaces": [
        "us",
        "uk",
        "de",
    ],
    "categories": ["electronics"],
}

# Run the Actor and wait for it to finish
run = client.actor("usestring/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 '{
  "marketplaces": [
    "us",
    "uk",
    "de"
  ],
  "categories": [
    "electronics"
  ]
}' |
apify call usestring/amazon-bestsellers --silent --output-dataset

```

## MCP server setup

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