# Amazon Search Results & Best Sellers Scraper (`xtracto/amazon-search-bestsellers`) Actor

Track where products rank on Amazon. Search mode returns every result for a keyword with its absolute rank across pages, sponsored ads flagged separately from organic positions. Best Sellers mode returns the top 100 of any category with rank, price, rating and reviews.

- **URL**: https://apify.com/xtracto/amazon-search-bestsellers.md
- **Developed by:** [Farhan Febrian Nauval](https://apify.com/xtracto) (community)
- **Categories:** E-commerce, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.33 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 Search Results & Best Sellers Scraper

Find out exactly where products rank on Amazon — search any keyword and get every result with its position, or pull the ranked top 100 of any Best Sellers category.

### Why use this actor

- **No account, no login, no API key.** Give it a keyword or a category and press Run.
- **True rank positions, counted across pages.** The first product on page 2 is rank 17, not rank 1 — so you can chart "my product moved from #12 to #19" without stitching pages together yourself.
- **Ads separated from real rankings.** Paid placements are flagged `isSponsored` and left out of the `organicPosition` ladder, so you always know your genuine organic rank rather than a number inflated by ad slots.
- **The full Best Sellers top 100**, each product with its exact rank, price, star rating and review count.
- **Rich rows out of the box:** product ID, title, price and currency, rating, review count, image, "Amazon's Choice" / "Best Seller" badges, and a clean product link.
- **Built for repeat runs.** Schedule it daily or weekly and every row is stamped with the moment it was collected, so rank history builds itself.
- **Stable JSON** ready for spreadsheets, databases and dashboards — export as JSON, CSV or Excel.

### How it works

1. Pick a mode: **Search results** for keyword rank tracking, or **Best Sellers** for category charts.
2. Enter your keywords (or paste search links you already use), or the categories you want to watch.
3. The actor opens each results page in order, page after page, and reads every product card on it.
4. Each product becomes one row, numbered continuously across pages so ranks stay comparable between runs.
5. Rows arrive in the dataset as they are collected, and you download them in whatever format you like.

You do not manage scrapers, browsers or blocks — retries and page handling happen automatically, and anything that goes wrong is reported as a clearly labelled row instead of quietly disappearing.

### Input

#### Search results mode

```json
{
  "mode": "search",
  "keywords": ["wireless earbuds"],
  "searchUrls": ["https://www.amazon.com/s?k=bluetooth+speaker"],
  "domain": "amazon.com",
  "maxPages": 3,
  "maxItems": 200,
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "US"
  }
}
```

#### Best Sellers mode

```json
{
  "mode": "bestsellers",
  "categories": ["electronics"],
  "categoryUrls": ["https://www.amazon.com/Best-Sellers-Electronics-Headphones/zgbs/electronics/172541"],
  "domain": "amazon.com",
  "maxPages": 2,
  "maxItems": 200,
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "US"
  }
}
```

| Field | Type | Description |
| --- | --- | --- |
| `mode` | string | `search` for keyword rank tracking, `bestsellers` for category top-100 charts. |
| `keywords` | array | Search terms, exactly as a shopper would type them. Each is searched separately. Search mode only. |
| `searchUrls` | array | Full Amazon search links, so you can reuse filters, sorting or department restrictions you set up in the browser. Page numbers are added for you. Search mode only. |
| `categories` | array | Category names as they appear in a Best Sellers link, e.g. `electronics`, `videogames`, `toys-and-games`. Best Sellers mode only. |
| `categoryUrls` | array | Full Best Sellers links, including sub-category pages. Best Sellers mode only. |
| `domain` | string | Which marketplace to use: `amazon.com`, `amazon.co.uk`, `amazon.de`, `amazon.ca`, `amazon.com.au`, `amazon.in`, `amazon.co.jp`. |
| `maxPages` | integer | Pages to walk per keyword or category. Best Sellers lists are only two pages long (the top 100). |
| `maxItems` | integer | Hard cap on rows for the whole run, counted across every keyword and category. |
| `maxConcurrency` | integer | How many keywords or categories to work on at the same time. |
| `proxyConfiguration` | object | Residential in the marketplace's own country is strongly recommended (US for amazon.com). |

### Output

#### Search results mode — real rows

A paid placement at the top of the page (note `organicPosition` is empty — ads never take an organic rank):

```json
{
  "_input": "wireless earbuds",
  "_source": "S1-search",
  "_scrapedAt": "2026-08-08T05:39:01Z",
  "recordType": "SEARCH_RESULT",
  "keyword": "wireless earbuds",
  "searchUrl": "https://www.amazon.com/s?k=wireless+earbuds",
  "domain": "amazon.com",
  "page": 1,
  "position": 1,
  "organicPosition": null,
  "isSponsored": true,
  "asin": "B0H5W39V6T",
  "title": "HAOYUYAN Wireless Earbuds, Sports Bluetooth Headphones, 80Hrs Playtime Ear Buds with LED Power Display, Noise Canceling Headset, IPX7 Waterproof Earphones for Workout/Running (Black)",
  "price": 426256.49,
  "priceText": "IDR 426,256.49",
  "currency": "IDR",
  "rating": 4.9,
  "reviewCount": 290,
  "badge": null,
  "isPrime": false,
  "imageUrl": "https://m.media-amazon.com/images/I/71cmAChhQKL._AC_UY218_.jpg",
  "productUrl": "https://www.amazon.com/dp/B0H5W39V6T"
}
```

An organic result carrying an "Amazon's Choice" badge:

```json
{
  "_input": "wireless earbuds",
  "_source": "S1-search",
  "_scrapedAt": "2026-08-08T05:41:23Z",
  "recordType": "SEARCH_RESULT",
  "keyword": "wireless earbuds",
  "searchUrl": "https://www.amazon.com/s?k=wireless+earbuds",
  "domain": "amazon.com",
  "page": 1,
  "position": 4,
  "organicPosition": 2,
  "isSponsored": false,
  "asin": "B0BTYCRJSS",
  "title": "Soundcore by Anker P20i True Wireless Earbuds, with Big Bass, 30H Playtime | Bluetooth 5.3, Water-Resistant, 2 Mics for AI Clear Calls, 22 Preset EQs, Customization via App",
  "price": 355332.24,
  "priceText": "IDR 355,332.24",
  "currency": "IDR",
  "rating": 4.4,
  "reviewCount": 112282,
  "badge": "Amazon's Choice",
  "isPrime": false,
  "imageUrl": "https://m.media-amazon.com/images/I/51Yya2WtvkL._AC_UY218_.jpg",
  "productUrl": "https://www.amazon.com/dp/B0BTYCRJSS"
}
```

And the first row of page 2, showing that ranks keep counting instead of restarting:

```json
{
  "_input": "wireless earbuds",
  "_source": "S1-search",
  "_scrapedAt": "2026-08-08T05:36:45Z",
  "recordType": "SEARCH_RESULT",
  "keyword": "wireless earbuds",
  "searchUrl": "https://www.amazon.com/s?k=wireless+earbuds&page=2",
  "domain": "amazon.com",
  "page": 2,
  "position": 17,
  "organicPosition": 17,
  "isSponsored": false,
  "asin": "B0H9KZXY4H",
  "title": "Wireless Earbuds, AI Translation Earbuds Real Time Touch Screen | 5 EQ Modes, 48H AI Ear Buds with ANC Noise Cancelling/Transparency Mode, IPX7 Waterproof, 164 Language/7 Translation Modes",
  "price": 479760.74,
  "priceText": "IDR 479,760.74",
  "currency": "IDR",
  "rating": 5.0,
  "reviewCount": 83,
  "badge": null,
  "isPrime": false,
  "imageUrl": "https://m.media-amazon.com/images/I/7190QBIncYL._AC_UY218_.jpg",
  "productUrl": "https://www.amazon.com/dp/B0H9KZXY4H"
}
```

| Field | Type | Description |
| --- | --- | --- |
| `keyword` | string | The search term this row was found under. |
| `searchUrl` | string | The exact results page this row came from. |
| `page` | integer | Which results page the product appeared on. |
| `position` | integer | Rank among all results, counted continuously across pages. Includes paid placements. |
| `organicPosition` | integer | Rank among unpaid results only. Empty for paid placements. |
| `isSponsored` | boolean | `true` when the product occupied a paid ad slot rather than earning its place. |
| `asin` | string | Amazon's product ID. |
| `title` | string | Product title as shown in the results list. |
| `price` | number | Price as a number, ready for charts and comparisons. |
| `priceText` | string | Price exactly as displayed, including the currency symbol. |
| `currency` | string | Currency of the price. Empty when no price was shown. |
| `rating` | number | Star rating out of 5. |
| `reviewCount` | integer | Number of customer ratings. |
| `badge` | string | Badge on the card, such as "Amazon's Choice" or "Best Seller". |
| `isPrime` | boolean | Whether the card advertised Prime delivery. |
| `imageUrl` | string | Product thumbnail. |
| `productUrl` | string | Clean link to the product page. |
| `_scrapedAt` | string | UTC time this row was collected — this is what turns repeat runs into rank history. |

#### Best Sellers mode — real rows

```json
{
  "_input": "electronics",
  "_source": "S1-bestsellers",
  "_scrapedAt": "2026-08-08T05:36:12Z",
  "recordType": "BESTSELLER",
  "categoryUrl": "https://www.amazon.com/Best-Sellers/zgbs/electronics",
  "categoryName": "Best Sellers in Electronics",
  "domain": "amazon.com",
  "page": 1,
  "bestSellerRank": 2,
  "asin": "B0DCH8VDXF",
  "title": "Apple EarPods Headphones with USB-C Plug, Wired Ear Buds with Built-in Remote to Control Music, Phone Calls, and Volume",
  "price": 17.87,
  "priceText": "$17.87",
  "currency": "USD",
  "rating": 4.6,
  "reviewCount": 16374,
  "imageUrl": "https://images-na.ssl-images-amazon.com/images/I/513OSdW4elL._AC_UL900_SR900,600_.jpg",
  "productUrl": "https://www.amazon.com/dp/B0DCH8VDXF",
  "hasDetail": true
}
```

```json
{
  "_input": "https://www.amazon.com/Best-Sellers-Electronics-Headphones/zgbs/electronics/172541",
  "_source": "S1-bestsellers",
  "_scrapedAt": "2026-08-08T05:41:49Z",
  "recordType": "BESTSELLER",
  "categoryUrl": "https://www.amazon.com/Best-Sellers-Electronics-Headphones/zgbs/electronics/172541",
  "categoryName": "Best Sellers in Headphones & Earbuds",
  "domain": "amazon.com",
  "page": 1,
  "bestSellerRank": 3,
  "asin": "B00NJ2M33I",
  "title": "Sony ZX Series Wired On-Ear Headphones, Black MDR-ZX110",
  "price": 248679.24,
  "priceText": "IDR 248,679.24",
  "currency": "IDR",
  "rating": 4.5,
  "reviewCount": 100312,
  "imageUrl": "https://images-na.ssl-images-amazon.com/images/I/41CiQ7hR31L._AC_UL900_SR900,600_.jpg",
  "productUrl": "https://www.amazon.com/dp/B00NJ2M33I",
  "hasDetail": true
}
```

| Field | Type | Description |
| --- | --- | --- |
| `categoryName` | string | The list this row belongs to, e.g. "Best Sellers in Electronics". |
| `categoryUrl` | string | The Best Sellers page this row came from. |
| `bestSellerRank` | integer | The product's place in the chart, 1–100, counted continuously across both pages. |
| `asin` | string | Amazon's product ID. |
| `title` | string | Product title. |
| `price` / `priceText` / `currency` | number / string / string | Price as a number, as displayed, and its currency. |
| `rating` | number | Star rating out of 5. |
| `reviewCount` | integer | Number of customer ratings. |
| `imageUrl` | string | Product thumbnail. |
| `productUrl` | string | Clean link to the product page. |
| `hasDetail` | boolean | `true` for the products Amazon shows in full on the chart page. Amazon reveals only the first 30 of every 50 ranks in full; the rest arrive with their rank and product ID so the 1–100 ladder has no gaps. Filter on `hasDetail: true` when you need price and rating on every row. |

#### When something goes wrong

Nothing is ever dropped in silence. A keyword or category that could not be collected produces a labelled row instead:

```json
{
  "_input": "this-category-does-not-exist-xyz",
  "_source": "S1-bestsellers",
  "_scrapedAt": "2026-08-08T05:38:22Z",
  "_error": "parse_no_results",
  "_errorDetail": "HTTP 200 with list markers but 0 items parsed on page 1 — https://www.amazon.com/Best-Sellers/zgbs/this-category-does-not-exist-xyz"
}
```

`_error` tells you which kind of problem it was: `no_results` (Amazon genuinely has nothing for that keyword), `robot_check` or `throttled` (Amazon declined to serve the page — try Residential proxy or a lower parallelism), `parse_no_results` (the page loaded but held no products), `no_input`, `not_found`, `fetch_failed`, `exception`.

### Notes and limits

- **Use Residential + the marketplace's own country.** Amazon shows prices, currency and delivery promises based on where the visitor appears to be. The search samples above were captured without a country-matched location, which is why they show IDR on amazon.com — with Residential + US you get USD. This is also what keeps ad slots and results stable, so it is the default in the input.
- **Results per page vary.** Amazon serves several layouts and a search page holds roughly 16 to 60 products. Raise `maxPages` if you need to reach deeper ranks.
- **Best Sellers charts are 100 products long**, split over two pages, and Amazon shows the first 30 of each 50 in full detail (see `hasDetail` above). Need price and rating for every one of the 100? Feed the product IDs into the Amazon Product & Best Sellers Rank Scraper below.
- **Paid placements move constantly.** Which products occupy ad slots differs between visitors and times of day, so `position` will fluctuate a little more than `organicPosition`. For rank tracking, compare `organicPosition` run over run.
- **Amazon changes its page layouts often.** If a layout change ever breaks collection, the run reports `parse_no_results` rows rather than returning a silently empty dataset.
- Lower `maxConcurrency` if runs come back with `throttled` rows — Amazon limits how quickly one visitor may page through results.

### Other Amazon actors in this collection

| Actor | What it gives you |
| --- | --- |
| [Amazon Product & Best Sellers Rank Scraper](https://apify.com/store?search=amazon-products-scraper) | Full detail for a product ID: every Best Sellers Rank, buy-box price and seller, availability, and a buy-box-competition signal. |
| [Amazon Reviews Scraper](https://apify.com/store?search=amazon-reviews-scraper) | Customer reviews for a product, with star rating, date, verified-purchase flag and review text. |

# Actor input Schema

## `mode` (type: `string`):

What to scrape. 'Search results' walks the result pages for your keywords and returns each product with its rank. 'Best Sellers' returns the ranked top 100 of a category.

## `keywords` (type: `array`):

Search terms to look up, exactly as a shopper would type them. Each keyword is searched separately and every product gets a rank for that keyword.

## `searchUrls` (type: `array`):

Paste full Amazon search URLs to reuse filters, sorting or department restrictions you set up in the browser (for example a price-filtered or brand-filtered search). Page numbers are added automatically.

## `categoryUrls` (type: `array`):

Full Amazon Best Sellers URLs, including sub-category pages. Copy them straight from the browser address bar.

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

Top-level category names as they appear in a Best Sellers link, for example 'electronics', 'videogames', 'toys-and-games', 'home-garden'.

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

Which Amazon marketplace to search. Keywords and category names are resolved on this marketplace; pasted URLs are used exactly as given.

## `maxPages` (type: `integer`):

How many result pages to walk for each keyword, search URL or category. A search page holds roughly 16 to 60 products depending on the layout Amazon serves. Best Sellers lists are only two pages long (the top 100), so higher values are ignored there.

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

Hard cap on how many rows this run returns, counted across all keywords and categories. Raise it when you track many keywords at once.

## `maxConcurrency` (type: `integer`):

How many keywords or categories to work on at the same time. Lower this if results come back incomplete.

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

Residential proxy in the marketplace's own country is strongly recommended (US for amazon.com). Amazon prices, currency and delivery promises change with the visitor's location, so a mismatched country returns prices in the wrong currency.

## Actor input object example

```json
{
  "mode": "search",
  "keywords": [
    "wireless earbuds"
  ],
  "searchUrls": [
    "https://www.amazon.com/s?k=bluetooth+speaker"
  ],
  "categoryUrls": [
    "https://www.amazon.com/Best-Sellers-Electronics-Headphones/zgbs/electronics/172541"
  ],
  "categories": [
    "electronics"
  ],
  "domain": "amazon.com",
  "maxPages": 3,
  "maxItems": 200,
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `keyword` (type: `string`):

Keyword as reported by the source.

## `position` (type: `string`):

Position in the result list. Whole number.

## `organicPosition` (type: `string`):

Organic Position as reported by the source.

## `isSponsored` (type: `string`):

Is Sponsored. Boolean value.

## `asin` (type: `string`):

Asin as reported by the source.

## `title` (type: `string`):

Title of the item.

## `price` (type: `string`):

Price of the item. Numeric value.

## `currency` (type: `string`):

ISO currency code of the price.

## `rating` (type: `string`):

Rating score. Numeric value.

## `reviewCount` (type: `string`):

Number of reviews. Whole number.

## `badge` (type: `string`):

Badge as reported by the source.

## `page` (type: `string`):

Page as reported by the source.

## `productUrl` (type: `string`):

Link to the product.

## `categoryName` (type: `string`):

Category Name as reported by the source.

## `bestSellerRank` (type: `string`):

Best Seller Rank as reported by the source.

## `hasDetail` (type: `string`):

Has Detail. Boolean value.

## `recordType` (type: `string`):

Which kind of row this is.

## `searchUrl` (type: `string`):

Link to the search.

## `priceText` (type: `string`):

Price Text as reported by the source.

## `isPrime` (type: `string`):

Is Prime. Boolean value.

## `imageUrl` (type: `string`):

Link to the image.

## `categoryUrl` (type: `string`):

Link to the category.

## `_input` (type: `string`):

The input value this row was produced from.

## `_source` (type: `string`):

Which extraction strategy produced the row.

## `_scrapedAt` (type: `string`):

UTC timestamp of the scrape, ISO 8601.

## `_error` (type: `string`):

Set only on diagnostic rows - why that target produced no data.

## `_errorDetail` (type: `string`):

Extra context for the 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 = {
    "mode": "search",
    "keywords": [
        "wireless earbuds"
    ],
    "searchUrls": [
        "https://www.amazon.com/s?k=bluetooth+speaker"
    ],
    "categoryUrls": [
        "https://www.amazon.com/Best-Sellers-Electronics-Headphones/zgbs/electronics/172541"
    ],
    "categories": [
        "electronics"
    ],
    "domain": "amazon.com",
    "maxPages": 3,
    "maxItems": 200,
    "maxConcurrency": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("xtracto/amazon-search-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 = {
    "mode": "search",
    "keywords": ["wireless earbuds"],
    "searchUrls": ["https://www.amazon.com/s?k=bluetooth+speaker"],
    "categoryUrls": ["https://www.amazon.com/Best-Sellers-Electronics-Headphones/zgbs/electronics/172541"],
    "categories": ["electronics"],
    "domain": "amazon.com",
    "maxPages": 3,
    "maxItems": 200,
    "maxConcurrency": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("xtracto/amazon-search-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 '{
  "mode": "search",
  "keywords": [
    "wireless earbuds"
  ],
  "searchUrls": [
    "https://www.amazon.com/s?k=bluetooth+speaker"
  ],
  "categoryUrls": [
    "https://www.amazon.com/Best-Sellers-Electronics-Headphones/zgbs/electronics/172541"
  ],
  "categories": [
    "electronics"
  ],
  "domain": "amazon.com",
  "maxPages": 3,
  "maxItems": 200,
  "maxConcurrency": 3
}' |
apify call xtracto/amazon-search-bestsellers --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,xtracto/amazon-search-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/HvK1mQef4pnGxQqLL/builds/1FKFhmfM7Q7PA8xWC/openapi.json
