Operating the API

Amazon Data API best practices

What separates an integration that runs unattended for months from one you babysit.

1. Always send a postcode

It is the single biggest quality lever. Without one, Amazon hides prices and images on a large share of listings. Pick one postcode per marketplace, store it in config and never vary it within a dataset — changing it mid-crawl makes your price series incomparable.

2. Cache by volatility, not by endpoint

Different fields decay at wildly different rates. Cache accordingly:

DataSuggested TTLWhy
Title, brand, images, bullets7 daysChanges only when the listing is edited.
Category taxonomy, GTIN mappings30 daysEffectively static.
Rating & review count24 hoursMoves slowly on established listings.
Best-seller rank6–24 hoursAmazon itself recomputes hourly at best.
Price, offers, availability15–60 minutesThe Buy Box genuinely moves this fast.
Deals15 minutesLightning deals expire quickly.

A catalogue of 10,000 ASINs refreshed hourly is 7.2M requests a month. The same catalogue with prices hourly and metadata weekly is closer to 7.3M — but split so that a metadata outage never stalls your pricing pipeline.

3. Respect the rate limit deliberately

Do not discover your ceiling by hitting it. Set your worker pool to your plan's per-second limit and pace batches to the second. Rate-limited requests cost nothing, but a retry storm adds latency and hides real failures.

4. Treat note as a first-class signal

An empty array with a note means "this could not be retrieved", not "there is nothing here". Log it distinctly. Alerting on count == 0 without checking note produces false positives on the endpoints where Amazon gates the surface.

Distinguishing the two
data = fetch("/influencers/posts", {"handle": handle})

if data.get("note"):
    logger.info("gated surface for %s: %s", handle, data["note"])
    metrics.increment("amazon.gated")
elif not data["posts"]:
    logger.warning("genuinely empty storefront: %s", handle)

5. Use the narrowest endpoint that answers your question

You wantUseNot
Aggregate rating only/products/reviews/top/products/reviews
Buy Box price/products/offers/products/details
An ASIN from a barcode/utility/gtin-to-asin/products/search
30 ranked products in a category/bestsellers30 × /products/details
A competitor's whole catalogue/sellers/productsrepeated searches

6. Make requests idempotent and resumable

Store progress per ASIN, not per job. A crawl that dies at item 8,400 of 10,000 should resume at 8,400 — not restart and burn 8,400 credits re-fetching what you already have.

7. Persist raw responses

Store the JSON you receive alongside your normalised rows. When you later discover a field you should have been extracting, you can backfill from your own archive instead of re-crawling and paying twice.

8. Monitor the right four numbers

Credits remaining

Straight off X-Credits-Remaining. Alert well before zero, not at it.

Error rate by status

A 429 spike is your pacing. A 502 spike is upstream. Do not aggregate them.

Null-price ratio

Climbing sharply usually means a dropped zip parameter.

Cache hit rate

From X-Cache. A sudden drop signals your key-space or query mix changed.

9. Keep test traffic on test keys

Issue an ac_test_ key for CI and staging. Test suites are the most common source of surprise credit burn, and a separate key means you can revoke or throttle them without touching production.

10. Handle the trademark and terms question up front

AmazonCrawler is independent and not affiliated with Amazon. You are responsible for making sure your use of the data complies with whatever terms apply to you and your jurisdiction — worth settling before you build a product on top. See our acceptable use policy.

Building something with an unusual shape — very high concurrency, a full-catalogue sweep, a residency requirement? Tell us about it. It is usually cheaper to design it together than to discover the limit in production.