DEV Community

huynhtanan
huynhtanan

Posted on

Track Amazon Best Sellers in 17 country stores with Python

If you're monitoring e-commerce trends, running a brand, or feeding a shopping assistant, you probably want what's selling on Amazon right now — not next week, and not just in the US.

Amazon publishes the Best Sellers and Hot New Releases charts for every category, in 17 country stores, updated every hour. Scraping those pages is cheap and doesn't need a login — this post shows how to do it from Python in three ways: today's top sellers, a cross-marketplace comparison, and a daily tracker that logs rank + price changes into SQLite.

Code is in github.com/huynhtanan/amazon-bestsellers-tracker (MIT). Disclosure: I built the Apify scraper this uses; it's pay-per-result at $1 per 1,000 products, and new Apify accounts get free monthly credit that covers tens of thousands of items.

Setup

pip install "apify-client>=3"
export APIFY_TOKEN=...   # https://console.apify.com/settings/integrations (free account)
Enter fullscreen mode Exit fullscreen mode

1. Today's top sellers in one category

import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("zet46/amazon-best-sellers-scraper").call(run_input={
    "marketplace": "co.uk",
    "listType": "bestsellers",         # or "new-releases"
    "categorySlugs": ["electronics"],
    "maxItemsPerCategory": 20,
})
for it in client.dataset(run.default_dataset_id).iterate_items():
    print(f'#{it["rank"]:>3}  {it["title"][:60]:60}  {it.get("priceText") or "   --":>8}  '
          f'{it["rating"]} ({it["reviewsCount"]:,})')
Enter fullscreen mode Exit fullscreen mode

Real output (UK, electronics):

#  1  Amazon Basics 20-Pack AA Alkaline High-Performance Batteries     £6.32  4.6 (930,935)
#  2  DURACELL Plus 9V Alkaline Batteries (2 Pack) 6LR61 | 100% Li     £5.42  4.7 (15,730)
#  3  Amazon Basics 40-Pack AA Alkaline Industrial Batteries, 1.5      £6.62  4.5 (101,364)
#  4  DURACELL 2032 Lithium Coin Batteries (4 Pack) 3V, CR2032 | U        --  4.7 (144,677)
#  5  DURACELL Plus AA Alkaline Batteries (30 Pack) 1.5V, LR06 | D    £15.41  4.8 (1,115)
#  6  Ring Battery Video Doorbell 2K (newest gen), DIY Wireless Do        --  4.2 (3,919)
#  7  Amazon Fire TV Stick HD (newest gen), free & live TV, Alexa         --  4.1 (5,055)
Enter fullscreen mode Exit fullscreen mode

For books you also get byline (author) and format (Hardcover / Paperback / Kindle Edition). Here's amazon.de's current top 5 books (fiction heavy, with an entry for the Bürgerliches Gesetzbuch — Germany's civil code):

#1  Murdoku 1: 80 Logikrätsel rund um mysteriöse Mordfälle      11,76 €   Manuel Garand        Taschenbuch
#2  Bürgerliches Gesetzbuch: mit AGG und Verjährung              8,32 €                        Taschenbuch
#3  Der Nachtzug (limitierte Auflage): Psychothriller           24,30 €   Sebastian Fitzek     Gebundene Ausgabe
#4  Murdoku 2: Auf Zeitreise                                    11,76 €   Manuel Garand        Taschenbuch
#5  Heimsuchung: Roman                                          13,08 €   Jenny Erpenbeck      Taschenbuch
Enter fullscreen mode Exit fullscreen mode

2. Compare one category across many marketplaces

Pass full URLs so each marketplace returns its own prices and currency without you keeping a (country, slug) mapping:

run = client.actor("zet46/amazon-best-sellers-scraper").call(run_input={
    "categoryUrls": [
        "https://www.amazon.com/gp/bestsellers/electronics",
        "https://www.amazon.co.uk/gp/bestsellers/electronics",
        "https://www.amazon.fr/gp/bestsellers/electronics",
        "https://www.amazon.it/gp/bestsellers/electronics",
        "https://www.amazon.co.jp/gp/bestsellers/electronics",
    ],
    "maxItemsPerCategory": 5,
})
Enter fullscreen mode Exit fullscreen mode

Output:

amazon.com:
  #1  blink plus plan with monthly auto-renewal                 $11.99  4.4 (281,100)
  #2  Apple EarPods Headphones with USB-C Plug                  $19.00  4.5 (19,026)
  #3  Apple AirTag (2nd Generation)                             $24.00  4.6 (11,866)

amazon.co.uk:
  #1  Amazon Basics 20-Pack AA Alkaline High-Performance B       £7.58  4.6 (930,935)
  #2  DURACELL Plus 9V Alkaline Batteries (2 Pack)               £6.50  4.7 (15,730)

amazon.fr:
  #1  DURACELL 2032 Piles Boutons au Lithium (Lot de 8)       11,99 €  4.7 (979)
  #2  TOCOL Coque pour iPhone 15, Compatible avec MagSafe,     8,57 €  4.6 (417)

amazon.it:
  #1  NEW'C Pellicola Vetro per iPhone 17/17 Pro/16 Pro        8,19 €  4.4 (306,728)
  #2  Amazon Basics, 36 batterie alcaline AAA                  8,58 €  4.6 (855,344)

amazon.co.jp:
  #3  NIMASO ガラスフィルム iPhone 17 用 保護フィルム 強化ガラス               ¥1,357  4.3
  #4  Amazonベーシック 単3形 アルカリ乾電池 20本 1.5V 保存期限10年                 ¥759  4.3
Enter fullscreen mode Exit fullscreen mode

A few things the data shows that are easy to miss if you only read amazon.com:

  • US electronics is dominated by Apple + Amazon devices. The UK is dominated by batteries (five of the top ten are AA / 9V / coin cells).
  • iPhone 17 is in the top-5 of both Italy and Japan as a case/accessory, before Apple's own cheapest earbuds show up. That's a signal for third-party accessory brands.
  • Review counts cross one million in multiple markets — much larger than I expected, and useful if you need "popularity floor" filters.

The scraper detects the marketplace and chart type (bestsellers / new-releases) per URL, so you can mix them in one request. It also sets the right lc-main + i18n-prefs cookies and Accept-Language header per country, so Amazon serves the local language and currency even though the outbound IP is in a single Apify data center.

3. Daily rank + price tracking in ~90 lines

Save one row per ASIN per day, print climbers, fallers, newcomers and dropouts. The whole thing fits in a SQLite table with 11 columns.

# track_rank.py — see github.com/huynhtanan/amazon-bestsellers-tracker/blob/main/python/track_rank.py
import os, sqlite3
from datetime import date
from pathlib import Path
from apify_client import ApifyClient

MARKETPLACE, LIST_TYPE, CATEGORY, TOP_N = "com", "bestsellers", "electronics", 100
DB = Path("amazon_rank.sqlite3")

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("zet46/amazon-best-sellers-scraper").call(run_input={
    "marketplace": MARKETPLACE, "listType": LIST_TYPE,
    "categorySlugs": [CATEGORY], "maxItemsPerCategory": TOP_N,
    "pagesPerCategory": (TOP_N + 29) // 30,
})
items = list(client.dataset(run.default_dataset_id).iterate_items())
today = date.today().isoformat()

with sqlite3.connect(DB) as con:
    con.execute("""CREATE TABLE IF NOT EXISTS ranks (
        run_date TEXT, marketplace TEXT, list_type TEXT, category TEXT,
        rank INTEGER, asin TEXT, title TEXT, price REAL, currency TEXT,
        rating REAL, reviews INTEGER,
        PRIMARY KEY (run_date, marketplace, list_type, category, asin))""")
    for it in items:
        con.execute("INSERT OR REPLACE INTO ranks VALUES (?,?,?,?,?,?,?,?,?,?,?)",
                    (today, MARKETPLACE, LIST_TYPE, CATEGORY,
                     it["rank"], it["asin"], it["title"],
                     it.get("price"), it.get("currency"),
                     it.get("rating"), it.get("reviewsCount")))
Enter fullscreen mode Exit fullscreen mode

First run on amazon.com electronics (truncated):

Amazon.com bestsellers / electronics on 2026-10-15
(60 products tracked)

  #  1  blink plus plan with monthly auto-renewal                        11.99 USD
  #  2  Apple EarPods Headphones with USB-C Plug, Wired Ear Buds with    19.00 USD
  #  3  Apple AirTag (2nd Generation): Tracker for Keychain, Wallet, a   24.00 USD
  #  4  Apple AirPods Pro 3 Wireless Earbuds with Active Noise Cancell  199.00 USD
  #  5  Apple AirPods 5 Wireless Earbuds with Active Noise Cancellatio  129.00 USD
Enter fullscreen mode Exit fullscreen mode

The full script also prints "new in the chart", "climbers (3+ positions up)", "fallers (3+ positions down)" and "dropped out" on day 2 and after — see the GitHub repo.

Because the data is a plain table, you can answer things like "which ASINs lost 10+ ranks since last week" with one SQL line:

WITH last_two AS (
  SELECT asin, title, rank,
         LAG(rank) OVER (PARTITION BY asin ORDER BY run_date) AS prev_rank
  FROM ranks WHERE marketplace='com' AND category='electronics')
SELECT asin, title, prev_rank, rank, rank - prev_rank AS delta
FROM last_two
WHERE prev_rank IS NOT NULL AND rank - prev_rank >= 10
ORDER BY delta DESC;
Enter fullscreen mode Exit fullscreen mode

Running it every day

Two options, both free:

  • Apify Scheduler (zero infrastructure). On the actor page click Schedule actor, pick a cron (e.g. daily 09:00), save your input. Then from any machine run the script above with client.actor(...).last_run().get() to pull the latest completed dataset. No local cron, no server.
  • Local cron / Windows Task Scheduler. Call python track_rank.py daily. Each run also triggers a fresh scrape, so this is enough on its own.

Cost

$1 per 1,000 products returned. Tracking the top 100 of one chart daily for a month is 3,000 products = $3. Watching five country stores for the same category is still only $15/month.

Skipped items (via minRating, minReviews, or dedupe) are not charged.

A few things that bit me while building this

  • Amazon serves the local language and currency based on cookies, not IP. From a US-based scraper, amazon.de returns prices in dollars by default. You need lc-main=de_DE, i18n-prefs=EUR and Accept-Language: de-DE,de;q=0.9 on every request to get euros and the German review-count label (Sternebewertungen). The scraper does this per-marketplace automatically.
  • Prices on listing pages are only shown for some categories. Books always show a price. Electronics shows the price for ~40-60% of items, which is why you see -- in the examples above. If you need prices on everything, chain the ASINs into a per-product Amazon scraper after this one — the ASIN is the Amazon-wide product ID.
  • Review-count parsing is UI-language sensitive. 1,214 ratings on amazon.com is three different words on amazon.de (Sternebewertungen), amazon.fr (évaluations), amazon.it (valutazioni), amazon.co.jp (個の評価). The scraper has a regex union over 15 UI languages; still, a few less-common marketplaces may leave reviewsCount empty — rank, asin, title, url, image and rating are always set.
  • Movers & Shakers / Most Wished For / Gift Ideas need a residential IP — Amazon serves them empty from datacenter IPs. The scraper currently supports Best Sellers and Hot New Releases, which cover the two charts most people actually track.

Feedback welcome

If you'd like a specific feature (a specific marketplace that's missing, SQLite → Google Sheets sync, a Discord alert webhook, residential-proxy mode for the gift charts), the repo issues are open and I ship fixes within a day.

Code and more examples: github.com/huynhtanan/amazon-bestsellers-tracker. Scraper: apify.com/zet46/amazon-best-sellers-scraper.

Related tutorials

Top comments (0)