Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For large-scale Amazon catalog collection, start with an authorized Amazon API—not a scraper that repeatedly downloads product pages. Use SearchItems to discover ASINs and GetItems to retrieve details, batching up to 10 ASINs per request. Amazon’s indexed Product Advertising API documentation says PA-API was to be deprecated on May 15, 2026; that date has passed. Before building a new integration, verify current Creators API access, quotas, fields, and retention rules for your marketplace. The Python example below is a signed PA-API reference for an account that still has valid access, not a substitute for that migration check.

What an ASIN is—and what it does not guarantee

An Amazon Standard Identification Number (ASIN) is a 10-character alphanumeric identifier for an item in Amazon’s catalog. Treat it as a marketplace-scoped lookup key in your pipeline: store it in uppercase, retain the marketplace and retrieval timestamp alongside it, and do not assume every ASIN is retrievable or that the same fields are available in every locale.

An ASIN is not a promise of a current offer, price, stock status, or product-page availability. An ID can be inaccessible, unavailable in the requested marketplace, or returned separately as an API error. Preserve that distinction in your data rather than interpreting every missing item as proof that the ASIN does not exist.

Choose the acquisition route before writing a crawler

Use Amazon’s documented API for production catalog data

For supported access, the API path is SearchItems for keyword-based discovery and GetItems for retrieval by known ASIN. It gives you structured responses and explicit error containers, and avoids making an HTML page parser responsible for changes to a site’s markup. Access, fields, quotas, and affiliate requirements depend on the API and marketplace; confirm them against Amazon’s current documentation and your account before deployment.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why scraping HTML is a different decision

HTML scraping means fetching and parsing rendered or server-delivered product pages. It can be fragile when layouts change, pages vary by locale or session, or automated requests encounter bot checks. More importantly, the fact that a crawler respects robots.txt does not itself grant a third party permission to collect or reuse the site’s data. Amazon’s Product Discovery Bot documentation describes that bot’s robots.txt behavior; that is not authorization for your scraper. Review the applicable Amazon terms, marketplace policies, privacy obligations, and data-retention rules before collecting or redistributing catalog information.

Compare the routes on authorization, freshness, field coverage, marketplace support, quotas, latency, failure handling, repeatability, and migration risk. If the current Creators API does not fit your field or access requirements, resolve that with the relevant policy and API documentation before substituting page scraping.

Plan the data pipeline around marketplace and fields

  1. Fix the scope. Select one marketplace and list the fields you actually need: identifiers, title, brand, images, offer information, browse nodes, or parent ASIN. Resource availability differs by locale.
  2. Discover and persist IDs. Use SearchItems with a keyword, search index, and marketplace parameters. Save returned ASINs and parent relationships before fetching detail records, so discovery can be resumed independently.
  3. Fetch in batches. Send at most 10 ASINs per GetItems request. Inspect both the successful Items collection and the Errors collection.
  4. Request a small payload. Ask only for the item information, images, browse-node data, offers, or parent-ASIN data that your use case needs. Validate exact resource names against the API version and marketplace you are using.
  5. Throttle and checkpoint. Keep concurrency bounded, rate-limit against the account’s current allowance, retry transient failures with backoff, and persist progress between batches.
  6. Normalize and audit. Uppercase and deduplicate ASINs; store marketplace, fetch time, status, and source operation. Keep raw responses only where the governing policy permits.
  7. Make migration a release gate. Amazon’s indexed PA-API documentation stated that PA-API would be deprecated on May 15, 2026. Since that date has passed, verify present Creators API requirements, access, quotas, field mappings, and retention rules before starting a new integration or shipping an old one.

Python example: signed PA-API requests for existing authorized access

The code below implements AWS Signature Version 4 for the documented PA-API request pattern. It is a reference for an account with current permission to use PA-API; it is not Creators API code. The endpoint and signing region are deliberately environment settings because they must match your selected marketplace and current Amazon instructions. Set them from the applicable official documentation rather than guessing or reusing a US value.

Install Python 3 and requests (python -m pip install requests). Set the environment variables listed below. Keep credentials out of source control and redact them from logs. Use an Associates partner tag and partner type only when your account and request are entitled to that affiliate API access.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import os
import json
import time
import random
import hashlib
import hmac
from datetime import datetime, timezone
from urllib.parse import urlparse

import requests

ENDPOINT = os.environ["PAAPI_ENDPOINT"]  # Current endpoint for your marketplace
REGION = os.environ["PAAPI_REGION"]      # Signing region from current API docs
MARKETPLACE = os.environ["PAAPI_MARKETPLACE"]
PARTNER_TAG = os.environ["PAAPI_PARTNER_TAG"]
ACCESS_KEY = os.environ["AWS_ACCESS_KEY_ID"]
SECRET_KEY = os.environ["AWS_SECRET_ACCESS_KEY"]
SERVICE = "ProductAdvertisingAPI"
PARTNER_TYPE = "Associates"
MIN_INTERVAL_SECONDS = 1.0  # Also enforce your account's actual quota.
_last_request = 0.0


def sign(key, message):
    return hmac.new(key, message.encode("utf-8"), hashlib.sha256).digest()


def signing_key(secret, date_stamp, region, service):
    key_date = sign(("AWS4" + secret).encode("utf-8"), date_stamp)
    key_region = hmac.new(key_date, region.encode("utf-8"), hashlib.sha256).digest()
    key_service = hmac.new(key_region, service.encode("utf-8"), hashlib.sha256).digest()
    return hmac.new(key_service, b"aws4_request", hashlib.sha256).digest()


def signed_headers(operation, payload):
    parsed = urlparse(ENDPOINT)
    host = parsed.netloc
    path = parsed.path or "/"
    body = json.dumps(payload, separators=(",", ":"), ensure_ascii=False)
    now = datetime.now(timezone.utc)
    amz_date = now.strftime("%Y%m%dT%H%M%SZ")
    date_stamp = now.strftime("%Y%m%d")
    target = f"com.amazon.paapi5.v1.ProductAdvertisingAPIv1.{operation}"
    headers = {
        "content-encoding": "amz-1.0",
        "content-type": "application/json; charset=utf-8",
        "host": host,
        "x-amz-date": amz_date,
        "x-amz-target": target,
    }
    canonical_headers = "".join(f"{name}:{headers[name].strip()}n" for name in sorted(headers))
    signed_names = ";".join(sorted(headers))
    canonical_request = "n".join([
        "POST", path, "", canonical_headers, signed_names,
        hashlib.sha256(body.encode("utf-8")).hexdigest(),
    ])
    scope = f"{date_stamp}/{REGION}/{SERVICE}/aws4_request"
    string_to_sign = "n".join([
        "AWS4-HMAC-SHA256", amz_date, scope,
        hashlib.sha256(canonical_request.encode("utf-8")).hexdigest(),
    ])
    signature = hmac.new(
        signing_key(SECRET_KEY, date_stamp, REGION, SERVICE),
        string_to_sign.encode("utf-8"), hashlib.sha256
    ).hexdigest()
    headers["Authorization"] = (
        f"AWS4-HMAC-SHA256 Credential={ACCESS_KEY}/{scope}, "
        f"SignedHeaders={signed_names}, Signature={signature}"
    )
    return body, headers


def call_api(operation, payload, attempts=5):
    global _last_request
    body, headers = signed_headers(operation, payload)
    for attempt in range(attempts):
        delay = MIN_INTERVAL_SECONDS - (time.monotonic() - _last_request)
        if delay > 0:
            time.sleep(delay)
        try:
            response = requests.post(ENDPOINT, data=body, headers=headers, timeout=30)
            _last_request = time.monotonic()
        except requests.RequestException:
            if attempt == attempts - 1:
                raise
            time.sleep(min(30, 2 ** attempt + random.random()))
            continue
        if response.status_code == 429 or response.status_code >= 500:
            if attempt == attempts - 1:
                response.raise_for_status()
            time.sleep(min(30, 2 ** attempt + random.random()))
            continue
        response.raise_for_status()
        return response.json()
    raise RuntimeError("Request attempts exhausted")


def get_items(asin_list):
    if not 1 <= len(asin_list) <= 10:
        raise ValueError("GetItems accepts 1 to 10 ASINs per request")
    payload = {
        "ItemIds": [asin.strip().upper() for asin in asin_list],
        "Marketplace": MARKETPLACE,
        "PartnerTag": PARTNER_TAG,
        "PartnerType": PARTNER_TYPE,
        "Resources": ["ItemInfo.Title", "Images.Primary.Large", "ParentASIN"],
    }
    return call_api("GetItems", payload)


def chunks(values, size=10):
    for start in range(0, len(values), size):
        yield values[start:start + size]


if __name__ == "__main__":
    # Supply ASINs from a durable queue or a saved discovery result.
    source = os.environ.get("ASINS", "").split(",")
    asins = list(dict.fromkeys(value.strip().upper() for value in source if value.strip()))
    for batch in chunks(asins):
        result = get_items(batch)
        for item in result.get("ItemsResult", {}).get("Items", []):
            print(json.dumps({"status": "ok", "item": item}, ensure_ascii=False))
        for error in result.get("Errors", []):
            print(json.dumps({"status": "error", "error": error}, ensure_ascii=False))

Example setup (replace the endpoint, region, marketplace, and partner tag with current values for your account):

export PAAPI_ENDPOINT="YOUR_MARKETPLACE_API_ENDPOINT"
export PAAPI_REGION="YOUR_SIGNING_REGION"
export PAAPI_MARKETPLACE="YOUR_MARKETPLACE_ID"
export PAAPI_PARTNER_TAG="YOUR_ASSOCIATES_PARTNER_TAG"
export AWS_ACCESS_KEY_ID="YOUR_ACCESS_KEY"
export AWS_SECRET_ACCESS_KEY="YOUR_SECRET_KEY"
export ASINS="B000000001,B000000002"
python asin_fetch.py

For discovery, use the same call_api function with a SearchItems payload rather than inventing ASINs:

payload = {
    "Keywords": "wireless keyboard",
    "SearchIndex": "YOUR_VALID_SEARCH_INDEX",
    "Marketplace": MARKETPLACE,
    "PartnerTag": PARTNER_TAG,
    "PartnerType": PARTNER_TYPE,
    "Resources": ["ItemInfo.Title", "Images.Primary.Large", "ParentASIN"],
}
result = call_api("SearchItems", payload)
items = result.get("SearchResult", {}).get("Items", [])
asins = [item["ASIN"] for item in items if item.get("ASIN")]

Persist each page of discovery before proceeding. If the operation’s current schema uses a page number or continuation field, follow that version’s pagination rules and save the page position with the results. Do not assume an old PA-API pagination pattern carries over to Creators API.

Scale safely: batches, quotas, retries, and checkpoints

Batch without losing item-level errors

GetItems supports up to 10 ASINs per request according to Amazon’s indexed Product Advertising API documentation. Send chunks no larger than 10, but never treat a successful HTTP response as proof that every ID succeeded: inspect the returned Items and Errors containers and associate errors with their relevant ASINs. Store status separately so a later retry targets only retryable failures.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Respect account-specific throughput

Amazon Associates Central’s help page, indexed in 2026, describes an initial rate of 1 request per second, with an increase of 1 request per second per $4,600 in shipped revenue, capped at 10 requests per second. This is account-dependent, not a universal capacity promise. Confirm the allowance currently attached to your account; enforce it with a token bucket or equivalent limiter and keep concurrency inside the same budget. The sample’s one-second interval is a conservative starting point, not an entitlement.

Retry selectively and make jobs resumable

  • Use bounded exponential backoff with jitter for throttling responses, transient server errors, and network interruptions.
  • Do not retry malformed requests, invalid credentials, or policy/access errors unchanged; correct the cause first.
  • Checkpoint completed batches and persist the IDs still pending. On restart, continue from the queue rather than repeating all discovery and retrieval work.
  • Set timeouts, cap attempts, and record request operation, marketplace, response status, and a redacted error summary.
  • For large jobs, use bounded workers and a shared limiter. Independent workers each sleeping one second can collectively exceed an account’s limit.

For reliability, build an idempotent upsert keyed by marketplace plus ASIN and retrieval timestamp. Save successful data separately from unavailable or failed IDs. If policy allows, retain raw responses to diagnose schema changes; do not retain or redistribute data contrary to current program rules.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Python wrappers, freshness, and storage choices

Python packages can reduce boilerplate around API models or extract ASIN-shaped identifiers from text and Amazon URLs. Treat them as convenience layers: pin the version, check maintenance activity and license, inspect the generated request and signing behavior, test their retries and field coverage, and verify support for the API you actually use. Keep a small direct-HTTP path or contract test so a wrapper change does not silently alter your requests.

Store the normalized ASIN, marketplace, requested fields, retrieval time, and per-item status. Prices and availability are time-sensitive; do not label them current unless the value was fetched and timestamped, and follow the program’s display and retention rules. A screenshot or page capture is not a substitute for structured API fields or permission to collect them.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Common errors and how to fix them

Symptom Likely cause What to check
Authorization/signature error Wrong secret, signing date, region, service name, host, or canonical request. Compare endpoint host and signing region with the selected marketplace’s current documentation; verify system time is synchronized; ensure the exact transmitted body is the body hashed for signing.
Access or partner-parameter rejection Account lacks current API access, or partner tag/type is missing or mismatched. Confirm enrollment and API eligibility, then use the current required partner parameters. Do not place credentials or tags in public source.
Throttling response Request rate or combined worker concurrency exceeds the account’s allowance. Lower the shared rate, reduce workers, honor backoff, and verify current account limits before resuming.
Some requested ASINs are absent IDs may be inaccessible, invalid for the marketplace, or returned as item-level errors. Inspect both Items and Errors; record an explicit status and retry only when the error is transient.
Missing field in an otherwise successful item Resource was not requested, is unavailable for the locale/item, or differs in the current API schema. Check the resource name and locale-specific availability, then request only supported fields.
Search returns fewer records than expected Keyword/search-index scope or pagination is incomplete; results are not a guarantee of a full catalog export. Validate the search parameters and paginate per the current operation’s documentation; checkpoint every page.
Legacy integration no longer works PA-API lifecycle, eligibility, or requirements may have changed after the stated May 15, 2026 deprecation date. Verify current Creators API documentation, access, quotas, fields, and migration rules before changing retries or switching to HTML scraping.

Or skip the browser setup

ScreenshotNeo is a website screenshot API, not an ASIN catalog API, so it does not replace SearchItems or GetItems. It can help when a permitted workflow needs a visual page capture rather than structured catalog fields. One Python request returns an image response:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

See the ScreenshotNeo API documentation for request options. Before capture it accepts the cookie/consent banner like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and each response identifies its page verdict and billing status. Its MCP server exposes screenshot tools to Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. ScreenshotNeo is made by Yorker Media. Learn more at ScreenshotNeo.

Sign up free for 1,000 screenshots a month—no card required.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.