SellerMagnet's estimated_monthly_sales is either Amazon's own 'bought in past month' figure or, for most ASINs, a model built from sales rank, reviews and listing age - and the two should not be trusted the same way. Call /amazon-product-statistics for the same ASIN and check stats.monthlySoldHistory: a value in its last entry means the estimate is anchored on Amazon's own number; an empty list means it is modeled, which is an order of magnitude, not a count.
Key Takeaways
- estimated_monthly_sales is anchored on Amazon's own 'bought in past month' figure when Amazon publishes one, modeled otherwise.
- Amazon's own wording for the figure calls it 'not an estimate' but a lower bound ('at least 1000'), and says most ASINs do not have it set.
- A low or 0 estimate on the modeled path reflects thin input data (no monthlySold, short rank history, few reviews), not a verified sales count.
- monthlySoldHistory on /amazon-product-statistics tells you which path produced a given estimate - an empty list means modeled.
- Rating data (needed for the modeled path) costs at most one extra token, and only when it was refreshed within 14 days.
Myth 1: is the estimate an exact sales count?
No. Where Amazon shows a 'bought in past month' figure, Amazon's own search-page copy for it is explicit that the figure is 'not an estimate' - but it is a lower bound: Amazon rounds it down into buckets ('1K+' means at least 1,000, not exactly 1,000). SellerMagnet's estimateMonthlySells() takes that figure and nudges it slightly above the bucket floor (round(sold * 1.215) + sold ** (1/5)); it never invents a number Amazon did not already publish for that path.
Myth 2: does every product get a 'bought in past month' figure?
No - Amazon's own wording for the figure says most ASINs do not have this value set at all. Amazon only starts showing it once a listing crosses some internal volume threshold, so a majority of products on any marketplace have no figure to anchor on, and SellerMagnet falls back to the rank/review/age model for them. The sample below, from a real category page, is typical: only one of three ranked ASINs carried the figure.
| Path | When it applies | What the number means |
|---|---|---|
| 1 ANCHOR | Amazon's own 'bought in past month' figure is set for this ASIN | estimate sits inside Amazon's rounding bucket ('1K+' = 1,000-1,999) |
| 2 MODEL | no such figure - most ASINs | sales rank, reviews and listing age; order of magnitude, not a count |
Myth 3: does a low estimate mean the product barely sells?
Not reliably. A low or 0 number on the modeled path can mean the product genuinely sells little, or it can mean the model had little to work with: a short rank history, few reviews, or a very new or very old listing (the model damps both ends). Before 2026-09-19 the estimate request did not include rating, so every product lacking monthlySold lost the review/rating half of the model and estimated 0 regardless of its real sales; the request now always sends rating=1, but the model is still only as good as its inputs - it has no idea when its own inputs are thin.
sales_confidence.py - which path produced this ASIN's estimate
from retry import get_with_retry
from sellermagnet import new_session
# A failed estimate or statistics call is a refunded 500 (both propagate as ApiError), so retrying
# costs nothing on that path; 404 means the ASIN is not on this marketplace, not a failure.
def classify_estimate(session, asin: str, marketplace_id: str) -> dict:
"""One ASIN's estimate plus WHY it has that value: anchored on Amazon's own 'bought in past
month' figure, or modeled from rank/reviews/age because Amazon shows no such figure for most
listings. A low or 0 estimate on the modeled path reflects thin signal (no monthlySold, a
short rank history, few reviews), not necessarily low sales."""
estimate = get_with_retry(session, "amazon-product-search-estimated-sells", asin=asin, marketplaceId=marketplace_id)
stats = get_with_retry(session, "amazon-product-statistics", asin=asin, marketplaceId=marketplace_id)
sold = (stats.get("stats") or {}).get("monthlySoldHistory") or [] # [["YYYY-MM", units], ...]
latest = sold[-1] if sold else None
anchored = latest is not None
return {
"asin": estimate["asin"],
"estimated_monthly_sales": estimate["estimated_monthly_sales"],
"sales_rank": estimate["sales_rank"],
"category": estimate["category"],
"basis": "anchored" if anchored else "modeled",
"amazon_bought_last_month": f"{latest[1]} (month {latest[0]})" if latest else None,
"note": (
"within Amazon's own rounding bucket" if anchored
else "order of magnitude only - no 'bought in past month' figure shown for this ASIN"
),
}
if __name__ == "__main__":
session = new_session()
print(classify_estimate(session, "B0CLTBHXWQ", "APJ6JRA9NG5V4")) # has monthlySold
print(classify_estimate(session, "B0NOFIGURE", "APJ6JRA9NG5V4")) # no monthlySold shown
Example output (illustrative ASINs)
{'asin': 'B0CLTBHXWQ', 'estimated_monthly_sales': 1218, 'sales_rank': 15, 'category': 'Videogiochi', 'basis': 'anchored', 'amazon_bought_last_month': '1200 (month 2026-09)', 'note': "within Amazon's own rounding bucket"}
{'asin': 'B0NOFIGURE', 'estimated_monthly_sales': 42, 'sales_rank': 88210, 'category': 'Casa e cucina', 'basis': 'modeled', 'amazon_bought_last_month': None, 'note': "order of magnitude only - no 'bought in past month' figure shown for this ASIN"}

How do I check a whole category, not just one ASIN?
Pull a page from /amazon-bestsellers for a category_id, then run the same anchored/modeled check per ASIN (get_with_retry() and new_session() come from the Python quickstart; category IDs come from the category ID guide). A row with no ASIN ("N/A") or one that 404s on this marketplace is skipped, not counted - the 404 is a real answer (not tracked here), never a billed retry target. count is capped at 50 and offset + count must not exceed 50 on this endpoint - the API returns a billed 400 past either limit.
category_confidence.py - anchored vs modeled share across a category page
from collections import Counter
from retry import get_with_retry
from sellermagnet import ApiError, new_session
from sales_confidence import classify_estimate
# 50 is the API's own page cap on /amazon-bestsellers (offset + count must also stay <= 50), so
# one category page is the largest sample this costs 1 credit for; the classify_estimate call
# below costs 2 more per ASIN (estimate + statistics).
def category_split(session, category_id: str, marketplace_id: str, sample: int = 10) -> dict:
page = get_with_retry(session, "amazon-bestsellers", category_id=category_id,
marketplaceId=marketplace_id, count=50)
rows = []
basis_counts = Counter()
for b in page["bestsellers"][:sample]:
asin = b.get("asin")
if not asin or asin == "N/A":
continue # a bestsellers row can carry asin "N/A"
try:
row = classify_estimate(session, asin, marketplace_id)
except ApiError as err:
if err.status == 404:
continue # not tracked on this marketplace
raise
basis_counts[row["basis"]] += 1
rows.append({"rank": b.get("rank"), "asin": row["asin"], "basis": row["basis"],
"estimated_monthly_sales": row["estimated_monthly_sales"]})
total = sum(basis_counts.values()) or 1
return {
"rows": rows,
"anchored_pct": round(100 * basis_counts["anchored"] / total, 1),
"modeled_pct": round(100 * basis_counts["modeled"] / total, 1),
}
if __name__ == "__main__":
result = category_split(new_session(), "281407", "ATVPDKIKX0DER", sample=6)
for row in result["rows"]:
print(row["rank"], row["asin"], row["basis"], row["estimated_monthly_sales"])
print(f"anchored {result['anchored_pct']}% / modeled {result['modeled_pct']}%")
Example output (illustrative category sample)
1 B0ANCHOR1 anchored 2004
3 B0MODEL001 modeled 55
5 B0MODEL002 modeled 19
anchored 33.3% / modeled 66.7%

Two credits to know, one to guess
The estimate call is one credit; checking monthlySoldHistory on /amazon-product-statistics to see which path it took is a second credit on the same ASIN. For a one-off research question, pay both. For a sweep over many ASINs where you only need the number, the estimate alone is enough - just treat a 0 or very small result as low-confidence rather than a verified zero.
Frequently Asked Questions
Is estimated_monthly_sales an exact sales count?
No. It is either Amazon's own rounded 'bought in past month' figure or, for the majority of ASINs that do not show one, a model output - an order of magnitude, not a count.
Why did an estimate come back as 0 or a very small number?
That ASIN has no 'bought in past month' figure and little else to model from (thin rank history, few reviews, a young or very old listing). It signals low confidence, not necessarily zero sales.
How do I know which path produced a given estimate?
Call /amazon-product-statistics for the same ASIN and read stats.monthlySoldHistory. A value in its last entry means the estimate was anchored; an empty list means it was modeled.
Does requesting the rating add a second credit every time?
At most one extra token, and only when the rating and review-count series were refreshed within the last 14 days; otherwise the call still costs the base token.
Which products does Amazon show the bought-last-month figure for?
Amazon's own wording for it calls it a lower bound ('at least 1000') and says most ASINs do not have the value set at all, so expect it on a minority of listings, weighted toward higher-volume ones.
Bottom line: estimated_monthly_sales is Amazon's own rounded figure when Amazon publishes one, and a rank/review/age model for the majority of ASINs that do not - check monthlySoldHistory on the same ASIN before treating a low number as a verified sales count. The sales estimate page and the bestsellers page cover both endpoints, and a free account includes 150 credits to check a category's worth yourself.