Amazon Best Sellers Rank (BSR) is a critical metric for sellers and market researchers. A product's BSR indicates its sales velocity relative to other products in the same category. Tracking BSR changes over time reveals seasonal trends, the impact of promotions, and competitive dynamics. This tutorial builds a BSR tracking pipeline that queries Amazon product data via the Scavio API, stores daily BSR snapshots, and detects significant ranking changes.
Prerequisites
- Python 3.8 or higher
- requests library installed
- A Scavio API key
- A list of ASINs to track
Walkthrough
Step 1: Define ASINs to track
Create a list of Amazon ASINs with their names for easy identification in reports.
PRODUCTS = {
"B09G9FPHY6": "Echo Dot 5th Gen",
"B07FZ8S74R": "Fire TV Stick 4K",
"B09XS7JWHH": "Sony WH-1000XM5",
}Step 2: Fetch product data including BSR
POST each ASIN to /api/v1/amazon/product. best_sellers_rank is an array covering the whole category tree, so the headline BSR is its first entry.
def get_product_data(asin: str) -> dict:
r = requests.post(
"https://api.scavio.dev/api/v1/amazon/product",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"asin": asin, "country": "us"}
)
r.raise_for_status()
product = r.json()["data"]
ranks = product.get("best_sellers_rank") or []
return {
"asin": asin,
"title": product.get("title", ""),
"bsr": ranks[0]["rank"] if ranks else None,
"bsr_category": ranks[0]["category"] if ranks else None,
"price": product.get("price"),
"rating": product.get("rating"),
}Step 3: Store daily snapshots
Append each day's BSR data to a CSV file for historical analysis. Include a timestamp for each reading.
import csv
from datetime import date
def save_bsr(data: dict) -> None:
with open("bsr_history.csv", "a", newline="") as f:
writer = csv.writer(f)
writer.writerow([
date.today().isoformat(),
data["asin"],
data["title"],
data["bsr"],
data["price"],
])Step 4: Detect significant changes
Compare current BSR against the previous reading and flag products with large rank movements.
def detect_changes(current: dict, previous: dict, threshold: float = 0.2) -> str | None:
if not current.get("bsr") or not previous.get("bsr"):
return None
curr_bsr = int(current["bsr"])
prev_bsr = int(previous["bsr"])
change_pct = (prev_bsr - curr_bsr) / prev_bsr
if abs(change_pct) >= threshold:
direction = "improved" if change_pct > 0 else "dropped"
return f"{current['title']}: BSR {direction} from #{prev_bsr} to #{curr_bsr} ({change_pct*100:+.0f}%)"
return NonePython Example
import os
import csv
import requests
from datetime import date
API_KEY = os.environ.get("SCAVIO_API_KEY", "your_scavio_api_key")
ENDPOINT = "https://api.scavio.dev/api/v1/amazon/product"
PRODUCTS = {"B09G9FPHY6": "Echo Dot 5th Gen", "B07FZ8S74R": "Fire TV Stick 4K"}
def get_bsr(asin: str) -> dict:
r = requests.post(ENDPOINT, headers={"Authorization": f"Bearer {API_KEY}"},
json={"asin": asin, "country": "us"})
r.raise_for_status()
p = r.json()["data"]
ranks = p.get("best_sellers_rank") or []
return {"asin": asin, "bsr": ranks[0]["rank"] if ranks else None, "price": p.get("price")}
if __name__ == "__main__":
today = date.today().isoformat()
with open("bsr_history.csv", "a", newline="") as f:
w = csv.writer(f)
for asin, name in PRODUCTS.items():
data = get_bsr(asin)
w.writerow([today, asin, name, data["bsr"], data["price"]])
print(f"{name}: BSR #{data['bsr']} | {data['price']}")JavaScript Example
const API_KEY = process.env.SCAVIO_API_KEY || "your_scavio_api_key";
const ENDPOINT = "https://api.scavio.dev/api/v1/amazon/product";
const fs = require("fs");
const PRODUCTS = { B09G9FPHY6: "Echo Dot 5th Gen", B07FZ8S74R: "Fire TV Stick 4K" };
async function getBSR(asin) {
const res = await fetch(ENDPOINT, {
method: "POST",
headers: { Authorization: `Bearer ${API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ asin, country: "us" })
});
const product = (await res.json()).data ?? {};
const ranks = product.best_sellers_rank ?? [];
return { bsr: ranks[0]?.rank ?? null, price: product.price };
}
async function main() {
const today = new Date().toISOString().slice(0, 10);
for (const [asin, name] of Object.entries(PRODUCTS)) {
const data = await getBSR(asin);
const line = `${today},${asin},${name},${data.bsr},${data.price}\n`;
fs.appendFileSync("bsr_history.csv", line);
console.log(`${name}: BSR #${data.bsr} | ${data.price}`);
}
}
main().catch(console.error);Expected Output
Echo Dot 5th Gen: BSR #3 | $29.99
Fire TV Stick 4K: BSR #7 | $24.99
bsr_history.csv:
2026-04-19,B09G9FPHY6,Echo Dot 5th Gen,3,$29.99
2026-04-19,B07FZ8S74R,Fire TV Stick 4K,7,$24.99
2026-04-18,B09G9FPHY6,Echo Dot 5th Gen,5,$29.99
2026-04-18,B07FZ8S74R,Fire TV Stick 4K,6,$24.99