Home / Blog / Is That Amazon Deal Real? Check Deal Prices Against Price History via API

Is That Amazon Deal Real? Check Deal Prices Against Price History via API

Check whether Amazon deals are real reductions: compare each deal price with the lowest Buy Box price of the 30 and 90 days before the deal started, and flag 'was' prices that were never the Buy Box price - one deals call plus one history call per deal, in Python.

October 12, 2026
5 min read
SellerMagnet Team
Share & Bookmark
Blueprint flow from today's Amazon deals through Buy Box price history to a verdict per deal

An Amazon deal is only a deal if its price is lower than what the product recently cost. To check, compare the deal price from /api/amazon-deals with the Buy Box price history from /api/amazon-product-statistics: the lowest price in the 30 and 90 days before the deal started, and the highest. A deal at or above the 30-day low is no reduction, and a 'was' price above the 90-day high was never the Buy Box price in that time.

Key Takeaways

  • One deals call returns up to 50 deals with deal price, 'was' price (basisPrice) and start time; one statistics call per deal adds the Buy Box price history.
  • Compare with the 30 and 90 days before the deal started, not before today, or the deal's own days count as history.
  • A deal price at or above the 30-day low is no reduction: the product sold that cheaply within the last month.
  • A basisPrice above the 90-day high was never the Buy Box price in those 90 days; the deals data does not say whether it is a List Price or a Typical Price.
  • In the EU, a trader announcing a price reduction must show the lowest price it applied in at least the 30 days before.

How can you tell if an Amazon deal is real?

Compare the deal price with what the product cost before the deal began. The Buy Box price - the featured offer most buyers see - gets an entry whenever a check finds a new value, so its history gives the lowest and highest recorded price of any window. Two numbers decide most deals: the lowest Buy Box price of the 30 days before the deal, and the highest of the 90 days before. Amazon itself marks 30-, 90- and 365-day lows on product pages and shows up to 365 days of price history; the API does the same check for a whole page of deals at once.

Verdicts per deal; the was-price flag, and notes on a short history or an unknown start, are added to any of the first three.
VerdictWhenWhat it means
Lowest in 90 daysAt or below the 90-day lowA real low - worth a look
Below the 30-day lowUnder the 30-day low onlyA cut; it was cheaper before
Not below the 30-day lowIt sold this cheaply this monthNo reduction - skip it
Was-price above the 90-day highOver 1 % above the 90-day highIgnore the stated saving

How do I check Amazon deals against price history in Python?

Fetch today's deals, then one statistics call per deal. prices_between() returns every recorded Buy Box price in effect during a window - the one in effect at its start plus every later change. The price history has no entry while nobody held the Buy Box, so the function also reads the holder history, where "-1" marks that time, and does not carry an old price across it. check() builds the 30-, 90- and 365-day windows from the deal's start, applies the verdicts and notes a short history or an unknown start. get_with_retry() comes from retry.py, new_session() and ApiError from sellermagnet.py in the Python quickstart.

deal_check.py - every deal against its 30- and 90-day Buy Box history

"""Deal check: is each deal's price really low against the Buy Box history, and is its 'was' price real?"""
import sys
import threading
from concurrent.futures import ThreadPoolExecutor
from datetime import date, timedelta

import requests

from retry import get_with_retry
from sellermagnet import ApiError, new_session

MARKETPLACE = "ATVPDKIKX0DER"                   # deals: any marketplace; statistics: 11 of them
MINOR = 100                                     # history prices are in minor units; 1 on amazon.co.jp
_local = threading.local()


def session():
    if not hasattr(_local, "session"):
        _local.session = new_session()
    return _local.session


def prices_between(history, holders, start: date, end: date) -> list[float]:
    """Recorded Buy Box prices in effect during [start, end): the one in effect at start plus every later one.

    The price history has no entry while nobody held the Buy Box; the holder history marks that time with
    "-1", so a price from before such a gap is not carried across it."""
    points = [(date.fromisoformat(d), p / MINOR) for d, p in history or []]
    points += [(date.fromisoformat(t[:10]), None) for t, seller in holders or [] if seller == "-1"]
    points.sort(key=lambda x: x[0])
    before = [p for d, p in points if d < start]
    return [p for p in before[-1:] + [p for d, p in points if start <= d < end] if p is not None]


def check(deal: dict) -> dict:
    price, was = (deal.get("dealPrice") or {}).get("priceTotal"), deal.get("basisPrice")
    row = {"asin": deal["asin"], "deal": price, "was": was, "low30": None, "low90": None, "high90": None,
           "low365": None, "verdict": "", "title": (deal.get("productTitle") or "")[:40]}
    if not price:
        return {**row, "verdict": "no deal price"}       # 0.0: the page price could not be read
    started = deal.get("dealStartTime") or "N/A"
    start = date.fromisoformat(started[:10]) if started != "N/A" else date.today()
    try:
        data = get_with_retry(session(), "amazon-product-statistics", asin=deal["asin"], marketplaceId=MARKETPLACE)
    except ApiError as err:
        return {**row, "verdict": f"error {err.status}"}
    except requests.RequestException as err:
        return {**row, "verdict": type(err).__name__}
    history, holders = data["stats"].get("buyBoxPriceHistory"), data.get("buyBoxSellerIdHistory")
    window = {days: prices_between(history, holders, start - timedelta(days=days), start) for days in (30, 90, 365)}
    if not window[30] or not window[90]:
        return {**row, "verdict": "no Buy Box price before the deal"}
    row.update(low30=min(window[30]), low90=min(window[90]), high90=max(window[90]), low365=min(window[365]))
    if price >= row["low30"]:
        verdict = "not below the 30-day low"             # the price was already this low recently
    elif price <= row["low90"]:
        verdict = "lowest in 90 days"
    else:
        verdict = "below the 30-day low"
    if was and was > row["high90"] * 1.01:
        verdict += "; was-price above the 90-day high"
    since = data.get("trackingSince")
    if since and date.fromisoformat(since[:10]) > start - timedelta(days=90):
        verdict += f"; tracked only since {since[:10]}"
    if started == "N/A":
        verdict += "; start unknown, measured from today"
    return {**row, "verdict": verdict}


if __name__ == "__main__":
    try:
        deals = get_with_retry(new_session(), "amazon-deals", marketplaceId=MARKETPLACE, count=50)["deals"]
    except (ApiError, requests.RequestException) as err:
        sys.exit(f"no deals: {err}")
    unique = list({d["asin"]: d for d in deals if d.get("asin") not in (None, "N/A")}.values())
    with ThreadPoolExecutor(max_workers=4) as pool:
        rows = list(pool.map(check, unique))
    order = {"lowest in 90 days": 0, "below the 30-day low": 1, "not below the 30-day low": 2}
    for r in sorted(rows, key=lambda r: order.get(r["verdict"].split(";")[0], 3)):     # best deals first
        was = f"{r['was']:.2f}" if r["was"] else "-"
        span = (f"30d low {r['low30']:.2f}  90d {r['low90']:.2f}-{r['high90']:.2f}  365d low {r['low365']:.2f}"
                if r["low90"] else "")
        print("  ".join(filter(None, [r["asin"], f"deal {r['deal']:.2f} was {was}", span, r["verdict"]])))

Output, best deals first (illustrative data)

B0EXAMPLE1  deal 24.99 was 34.99  30d low 29.99  90d 29.99-34.99  365d low 17.99  lowest in 90 days
B0EXAMPLE8  deal 44.99 was 54.99  30d low 54.99  90d 44.99-54.99  365d low 44.99  lowest in 90 days
B0EXAMPLE9  deal 21.99 was 25.99  30d low 25.99  90d 25.99-25.99  365d low 25.99  lowest in 90 days; tracked only since 2026-09-23
B0EXAMPLE3  deal 24.99 was 39.99  30d low 29.99  90d 19.99-29.99  365d low 19.99  below the 30-day low; was-price above the 90-day high
B0EXAMPLE2  deal 34.99 was 79.99  30d low 34.99  90d 34.99-39.99  365d low 34.99  not below the 30-day low; was-price above the 90-day high
B0EXAMPLE6  deal 49.99 was 59.99  30d low 49.99  90d 49.99-59.99  365d low 49.99  not below the 30-day low; start unknown, measured from today
B0EXAMPLE4  deal 0.00 was 19.99  no deal price
B0EXAMPLE5  deal 15.00 was -  error 404
B0EXAMPLE7  deal 29.99 was 39.99  no Buy Box price before the deal
Blueprint step chart of a Buy Box price falling from 39.99 to 34.99 before a deal priced at 34.99
Illustrative: the deal price 34.99 was already the Buy Box price for weeks - and the 'was' price 79.99 never was.

What do the deals and the history contain?

Deals carry dealPrice.priceTotal (0.0 when the page price could not be read), basisPrice (null when no reference price is shown) and dealStartTime (ISO 8601 UTC, or "N/A" - then the script measures from today and says so). The Buy Box history is in minor units - 3499 is 34.99; trackingSince says how far back it goes. The deal price is the item price; the Buy Box history includes shipping, so on offers that charge shipping the deal can look cheaper than it was.

One deal and the history the script reads (trimmed, illustrative values)

{
  "deal": {
    "asin": "B0EXAMPLE2",
    "dealPrice": {"priceTotal": 34.99, "priceCurrency": "USD"},
    "basisPrice": 79.99,
    "savings_percentage": 56,
    "dealStartTime": "2026-10-11T08:00:00.000Z"
  },
  "statistics": {
    "trackingSince": "2024-01-10",
    "buyBoxSellerIdHistory": [["2026-06-15 09:12:00", "A1EXAMPLESELLER"]],
    "stats": {
      "buyBoxPriceHistory": [["2026-06-15", 3999], ["2026-08-14", 3699], ["2026-09-18", 3499]]
    }
  }
}

The EU 30-day rule

Article 6a of Directive 98/6/EC, added by the Omnibus Directive, requires a trader announcing a price reduction to show the lowest price it applied during at least the 30 days before. The script compares against the Buy Box price across all sellers, not one trader's own prices - it is a buyer's check, not a compliance check.

Blueprint table of the deal verdicts, when each applies and what it means for a buyer or a reseller
Three verdicts on the price, one flag on the stated saving.

Which deals are worth checking first?

The ones with the biggest stated saving: an inflated 'was' price shows up there first. One deals call and jq list every deal whose 'was' price is at least 1.5 times the deal price - one credit, then check only those against the history. The deals API guide covers department filters and lightning deals, the price history guide the other price series. The 365-day low puts a Black Friday deal next to the summer sales outside the 90-day window; for a message when a watched product drops, see the Telegram price tracker.

Deals whose 'was' price is 1.5x the deal price or more

curl -sG "https://sellermagnet-api.com/api/amazon-deals" \
  -H "X-Api-Key: $SELLERMAGNET_API_KEY" --max-time 120 \
  --data-urlencode "marketplaceId=ATVPDKIKX0DER" \
  --data-urlencode "count=50" \
  | jq -r 'if .success then .data.deals[]
           | select(.basisPrice != null and .dealPrice.priceTotal > 0 and .basisPrice >= 1.5 * .dealPrice.priceTotal)
           | "\(.asin)  \(.dealPrice.priceTotal) was \(.basisPrice)  \(.productTitle[:50])"
           else error(.message) end'

Frequently Asked Questions

How do I know if an Amazon deal is a real discount?

Compare the deal price with the lowest Buy Box price of the 30 days before the deal started. If the product already sold at that price or lower, the deal is no reduction.

What does a 'was' price above the 90-day high mean?

The stated reference price was never the Buy Box price in the 90 days before the deal. Amazon says a List Price reflects the suggested retail price and a Typical Price what customers recently paid on Amazon; the deals data does not say which one basisPrice is.

How many credits does a deal check cost?

One for up to 50 deals and one statistics call per deal checked - about 51 credits for a full page, plus one for each 502 or 503 that get_with_retry() retries.

Which marketplaces are covered?

Deals work on every marketplace the API supports; the price history covers US, UK, DE, FR, IT, ES, JP, CA, IN, MX and BR. Set MINOR to 1 on amazon.co.jp.

Why measure from the deal's start, not from today?

A deal that started three days ago has three days of deal prices in the recent history. Measuring from the start keeps them out of the comparison.

Bottom line: one deals call and one history call per deal show which deals are real lows, which are last month's price with a new badge, and which 'was' prices never happened. A free account includes 150 credits - enough to check two full deal pages before Black Friday.

Ready to Extract Amazon Data at Scale?

Start building with SellerMagnet API today. Real-time product data, competitive pricing, and review analytics at your fingertips.

150 free API credits • No credit card required • Cancel anytime