Track Amazon Best Sellers ranks with Python
Amazon Best Sellers lists change through the day, and a product entering the top 100 of a category is an early signal for sellers and brand managers. Amazon shows only the current list.
arcadium/amazon-products reads ranked lists (Best Sellers, New Releases, Movers & Shakers) per category. Saving one snapshot a day gives you the history Amazon does not keep.
Cost of this example on the Apify Free plan: 100 × $0.00531 = $0.531 ($0.288 on the Apify Gold plan and higher), plus $0.001 per GB of memory when the run starts.
What you need
- An Apify account and API token.
- Python 3.10 or newer with
apify-client3.x. - The category path from the Best Sellers URL, for example
kitchenfromamazon.com/gp/bestsellers/kitchen.
Step 1: Run it in the Apify Store (no code)
- Open arcadium/amazon-products on the Apify Store and sign in (a free Apify account works).
- Clear Search terms and enter the category path in Categories (Best Sellers, New Releases, Movers & Shakers), for example
kitchen. - Keep Ranked lists on Best Sellers and set Max ranks per list to 100.
- Set Amazon store to
US(or another store). - Optional: set a maximum cost per run in the run options as a hard cap.
- Click Start. Rows appear in the Output tab; export them as JSON, CSV or Excel.
The same input as JSON (paste it in the JSON tab of the input form):
{
"categories": [
"kitchen"
],
"listTypes": [
"bestsellers"
],
"maxResultsPerList": 100,
"marketplace": "US"
}
Step 2: Call it over the Apify API
One HTTP call runs the actor and returns its rows. It suits runs up to about five minutes; for longer runs start the run asynchronously and read the dataset when it finishes.
curl -X POST "https://api.apify.com/v2/acts/arcadium~amazon-products/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"categories":["kitchen"],"listTypes":["bestsellers"],"maxResultsPerList":100,"marketplace":"US"}'
Step 3: Run it from Python
With apify-client 3.x, call() returns a Run object: read the dataset id as run.default_dataset_id (older examples use run["defaultDatasetId"], which no longer works).
# pip install "apify-client>=3"
import csv, datetime, glob, os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("arcadium/amazon-products").call(run_input={
"categories": ["kitchen"], "listTypes": ["bestsellers"],
"maxResultsPerList": 100, "marketplace": "US",
})
rows = [r for r in client.dataset(run.default_dataset_id).iterate_items() # apify-client 3.x
if r.get("rowType") == "bestseller"]
today = datetime.date.today().isoformat()
keys = ["rank", "asin", "title", "price", "rating", "ratingCount", "url"]
previous = sorted(glob.glob("bestsellers-kitchen-*.csv"))
with open(f"bestsellers-kitchen-{today}.csv", "w", newline="") as f:
w = csv.DictWriter(f, fieldnames=keys, extrasaction="ignore")
w.writeheader()
w.writerows(rows)
if previous:
with open(previous[-1]) as f:
before = {r["asin"]: int(r["rank"]) for r in csv.DictReader(f)}
for r in rows:
if r["asin"] not in before:
print("new in top 100:", r["rank"], r["asin"], r["title"][:70])
Step 4: Run it from JavaScript
// npm install apify-client
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('arcadium/amazon-products').call({
"categories": [
"kitchen"
],
"listTypes": [
"bestsellers"
],
"maxResultsPerList": 100,
"marketplace": "US"
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
Step 5: Ask an AI assistant (MCP)
Apify’s hosted MCP server turns the actor into one tool. Add it to Claude, Cursor, VS Code or any MCP client:
{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com/?tools=arcadium/amazon-products",
"headers": {
"Authorization": "Bearer <APIFY_TOKEN>"
}
}
}
}Then ask, for example:
Use arcadium/amazon-products to read the top 50 Amazon.com Best Sellers in the kitchen category. Group them by product type and give the price range of each group.
More clients and the local setup on the MCP page.
Run it every day
Run the script from cron, or schedule the input as an Apify task and fetch its last run with GET https://api.apify.com/v2/acts/arcadium~amazon-products/runs/last/dataset/items?status=SUCCEEDED. For the fastest movers, add movers-and-shakers to Ranked lists: those rows carry rankChangePercent.
Output fields
Every row has a rowType; filter on it first. Failed inputs come back as free rows with a code and message. The fields this tutorial uses, from the actor’s dataset schema:
| Field | What it holds |
|---|---|
rowType | Kind of row. Filter on this first. 'searchResult': one search result card (charged as search-result). 'bestseller': one entry of a Best Sellers, New Releases, Movers & Shakers, Most Wished For or Gift Ideas list (charged as bestseller). 'product': one light product row with Buy Box and offers (charged as product). 'error': an input that gave no data; see code and message (free). |
listType | List rows: bestsellers, new-releases, movers-and-shakers, most-wished-for or most-gifted. |
category | List rows: category path as in the list URL, e.g. 'electronics/172541'; empty for the all-departments list. |
rank | List rows: rank in the list (1 = top). |
asin | Amazon product id (10 letters and digits), e.g. B0DCH8VDXF. |
title | Product title as the store shows it. Null on rank-only list entries (detailsComplete false). |
price | Search and list rows: price shown on the card, as a number in the store's currency (e.g. 19.99). Null when the card shows no price (unavailable, variants only). |
rating | Average star rating, 0 to 5, e.g. 4.5. Null when the product has no ratings. |
ratingCount | Number of ratings (global ratings on product rows). |
url | Canonical product link https://www.amazon.<store>/dp/<ASIN>. |
All fields: Amazon Product & Best Sellers Scraper guide.
Cost per run
Pay per event: you pay for the rows delivered, at the actor’s live Apify price on 2026-11-01. Error, coverage and summary rows are free.
| What | Rows | Price per row (Free plan) | Subtotal |
|---|---|---|---|
| Best Sellers row: 1 category, top 100 | 100 | $0.00531 | $0.531 |
Cost of this example on the Apify Free plan: 100 × $0.00531 = $0.531 ($0.288 on the Apify Gold plan and higher), plus $0.001 per GB of memory when the run starts. Higher Apify plans pay less per row. The Store page always has the current price.
Limitations
- Ranks 51-100 come from the second page of the list; set Max ranks per list to 50 to halve the cost.
- Prices are those a logged-out shopper in the store’s country sees, without a postcode.
- Search, ranked lists and the light product row only. The full product page (bullets, brand, BSR, variations, dimensions) is not part of this actor.
- Customer reviews are not collected: Amazon shows them only to signed-in visitors, and we never sign in.
- Delivery and prices are those of a shopper in the store's country without a postcode; a specific postcode needs a sign-in, so it is not supported.
- Search results follow Amazon's own ranking and personalisation for a logged-out visitor; ads and positions move during the day.
- Amazon answers some requests with a captcha or a "Something went wrong" page. The actor retries those on a new IP; inputs that still fail come back as free
blockedorunavailablerows.
Links
- Amazon Product & Best Sellers Scraper: fields, price table and sample output
- How to use Amazon Product & Best Sellers Scraper: every input field, n8n, LangChain
- arcadium/amazon-products on the Apify Store
- All tutorials