Amazon Data API response format
Flat JSON objects with stable field names. No envelope, no data.data,
no per-endpoint surprises in how success is signalled.
Shape
Success is the HTTP status. A 2xx body is the payload itself — there
is no success: true flag to check. Errors always carry a top-level
error object (or detail for validation).
{
"page": 1,
"sort": null,
"count": 20,
"query": "wireless mouse",
"results": [
{
"url": "https://www.amazon.com/dp/B07CMS5Q6P/ref=sr_1_1_sspa",
"asin": "B07CMS5Q6P",
"badge": "Best Seller",
"image": "https://m.media-amazon.com/images/I/51sg9BLSMTL.jpg",
"price": {
"amount": 29.99,
"display": "$29.99",
"currency": "USD",
"list_price": 49.99
},
"prime": false,
"title": "Logitech G305 Lightspeed Wireless Gaming Mouse - Black | HERO sensor, 12,000 DPI, Six programmable buttons, 250-hour battery, On-board memory",
"rating": 4.6,
"delivery": "FREE delivery Mon, Aug 10 on $35 of items shipped by Amazon",
"position": 4,
"sponsored": true,
"reviews_count": 39364,
"bought_past_month": "10K+ bought in past month"
},
{
"url": "https://www.amazon.com/dp/B005EJH6Z4/ref=sr_1_2_ffob_sspa",
"asin": "B005EJH6Z4",
"badge": null,
"image": "https://m.media-amazon.com/images/I/61YQeAUIboL.jpg",
"price": {
"amount": 12.58,
"display": "$12.58",
"currency": "USD",
"list_price": null
},
"prime": false,
"title": "Amazon Basics 2.4 GHz Wireless Optical Computer Mouse with USB Nano Receiver",
"rating": 4.5,
"delivery": "FREE delivery Mon, Aug 10 on $35 of items shipped by Amazon",
"position": 5,
"sponsored": true,
"reviews_count": 69507,
"bought_past_month": "10K+ bought in past month"
}
],
"marketplace": "US",
"has_next_page": true,
"total_results": 42555
}
Field conventions
Prices
Always an object, never a bare string or float. display is what Amazon
showed; amount is the parsed number in
currency. list_price is the struck-through
price where one exists, otherwise null.
Nulls mean “absent upstream”
A null is never a parsing shortcut — it means Amazon did not serve
that field for that listing. badge: null means no badge;
author: null on a review means Amazon rendered a linkless variant with
no reviewer name. Treat null and missing as the same thing.
Lists are always present
Array fields are [] when empty, never null.
You can iterate without a guard. Paired counts (count,
total_results) always match the array you were given.
count vs total_results
| Field | Meaning |
|---|---|
| count | Items in this response. |
| total_results | Amazon's claimed total across all pages. Approximate, and it drifts between requests — treat it as a hint, not a contract. |
| has_next_page | Authoritative. Use this to drive pagination, not arithmetic on total_results. |
The note field
Some Amazon surfaces are client-rendered or gated behind encrypted lazy-load calls. Where we cannot extract something, the response says so explicitly rather than returning a plausible-looking empty object.
{
"handle": "thehomeedit",
"marketplace": "US",
"count": 0,
"posts": [],
"note": "Influencer storefronts render posts client-side; the served HTML contains no post nodes."
}
note before treating count: 0 as
“this creator has no posts”. The endpoints that can return one are flagged in the
API Reference.
Diagnostic headers
| Header | Example | Meaning |
|---|---|---|
| X-Cache | HIT | Served from the in-process cache. |
| X-Response-Time-Ms | 412 | Server-side processing time. |
| X-Credits-Cost | 1 | Credits this call consumed. |
| X-Credits-Remaining | 24831 | Credits left this period. |
| X-Credits-Reset | 2026-09-03T… | When the quota resets. |
| X-RateLimit-Limit | 15 | Requests per second on your plan. |
Reacting to your own budget
response = requests.get(url, headers=HEADERS, params=params)
remaining = int(response.headers.get("X-Credits-Remaining", 0))
if remaining < 1000:
logger.warning("Credits low: %s left, resets %s",
remaining, response.headers["X-Credits-Reset"])
if response.headers.get("X-Cache") == "MISS":
metrics.timing("amazon.upstream_ms", int(response.headers["X-Response-Time-Ms"]))
Content type and encoding
Everything is application/json; charset=utf-8. Titles and review
bodies contain the original Unicode — emoji, CJK, RTL scripts and typographic quotes come through
unescaped. Responses are gzip-compressed when your client advertises support.
CORS
The API sends Access-Control-Allow-Origin: * and exposes the
diagnostic headers above, so browser clients can read them. That said — calling the API directly
from a browser means shipping your key to every visitor. Proxy through your own backend.