TagX Product Scraping API

Base URL: https://amzapi.tagxdata.com

The API has two kinds of endpoints:

EndpointMethodTypePurposeCost
/creditsGETCheck remaining credit balanceFree
/pdpPOSTsyncGet product details from a product URL$0.10
/scrapePOSTasyncSubmit a reviews scrape jobfrom $0.02
/result/{request_id}GETasyncFetch the result of a submitted jobFree

Authentication

Every request must include your API key in the x-api-key header.

x-api-key: your_api_key_here
🔑 Keep your API key secret. Never expose it in client-side code or public repositories.

Check Credits

GET /credits

Returns the remaining credit balance for the authenticated user. This endpoint is free.

Example

curl -X GET "https://amzapi.tagxdata.com/credits" \
  -H "x-api-key: your_api_key_here"
import requests

resp = requests.get(
    "https://amzapi.tagxdata.com/credits",
    headers={"x-api-key": "your_api_key_here"},
)
print(resp.json())   # {'credits': 10.0}

Response

{
  "credits": 10.0
}

Product Details synchronous $0.10 / request

POST /pdp

Fetches a product page and returns the parsed product details as JSON in the same response — there is no polling. The URL is validated first: it must be a valid product URL from a supported marketplace. Invalid or non-product URLs are rejected before any credits are charged.

🌍 Works across all supported marketplace regions and country domains. Prices are returned in the marketplace's own local currency.

Request Body

FieldTypeRequiredDescription
urlstringYesFull product URL. It must contain a product ID (for example /dp/PRODUCTID).

Pricing

Each successful call costs $0.10 (or your account's custom PDP rate). If the page cannot be fetched, the charge is automatically refunded.

Example

curl -X POST "https://amzapi.tagxdata.com/pdp" \
  -H "x-api-key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.example.com/dp/PRODUCTID"
  }'
import requests

resp = requests.post(
    "https://amzapi.tagxdata.com/pdp",
    headers={
        "x-api-key": "your_api_key_here",
        "Content-Type": "application/json",
    },
    json={"url": "https://www.example.com/dp/PRODUCTID"},
)

result = resp.json()
product = result["data"]
print(product["title"], product["price"]["current"])

Response

The parsed product is returned under data:

{
  "request_id": "550e8400-e29b-41d4-a716-446655440000",
  "cost": 0.10,
  "data": {
    "asin": "PRODUCTID0",
    "title": "Example Product Title - Variant, Size, Colour",
    "price": { "current": "1900", "list_price": null },
    "images": [ "https://images.example.com/i/product-1_large.jpg", "..." ],
    "description": "",
    "features": [ "Key selling point one ...", "Key selling point two ...", "..." ],
    "brand": "Example Brand",
    "brand_url": "https://www.example.com/stores/ExampleBrand/page/...",
    "category": [],
    "rating": {
      "average": "4.5",
      "count": "78",
      "breakdown": { "five_star": "...", "four_star": "...", "three_star": "...", "two_star": "...", "one_star": "..." }
    },
    "seller": {},
    "variants": [ "16.9 Fl Oz (Pack of 1)", "33.8 Fl Oz (Pack of 1)" ],
    "additional_details": {},
    "coupon": null,
    "coupon_details": null,
    "prime_flag": "Yes",
    "subscribe_and_save": "YES",
    "video": [],
    "feature_bullets_count": 5,
    "count_of_images": 10,
    "amazons_choice_flag": "YES",
    "best_seller_flag": "NO",
    "climate_pledge_friendly": "YES",
    "small_business_badge": "NO"
  }
}

Field reference

FieldDescription
asinThe product's 10-character identifier.
price.currentCurrent price as digits with no separators, e.g. "1900" = 19.00 in the marketplace currency. null if unavailable.
price.list_priceOriginal / struck-through price including its currency symbol (e.g. "$24.99"), or null.
images / count_of_imagesMain gallery image URLs and their count.
features / feature_bullets_count"About this item" bullet points and their count.
ratingaverage stars, total count, and per-star breakdown. The breakdown may be empty when the marketplace loads it lazily for low-review products.
variantsAvailable variant labels (size, color, style, ...).
additional_detailsKey/value pairs from the product information / specification table.
badge flagsProgram / eligibility flags such as fast-shipping, subscription, editor's-choice, best-seller, eco-friendly and small-business badges. Each is returned as "Yes"/"YES" or "No"/"NO".

A field that is not present on a given product is returned empty (null, [], or {}) rather than omitted, so the response shape is always the same.

Reviews asynchronous

Scraping reviews can take a while, so it runs as a background job in two steps:

  1. Submit the jobPOST /scrape with the product URL. You immediately get back a request_id. Credits are charged at submission.
  2. Poll for the resultGET /result/{request_id}. While the job runs you receive HTTP 202 (still processing); once finished you receive HTTP 200 with the review data.
💡 Poll /result every few seconds until you get a 200. If the job fails during processing you receive a 403 and your credits are automatically refunded.

POST /scrape

Submits a reviews-scraping job for a product URL and returns a request_id.

Request Body

FieldTypeDefaultDescription
urlstringRequired. Full product URL.
all_reviewsbooleantruetrue = scrape the full review history (all pages). false = a lighter, single-batch scrape. Ignored when pages is set.
reviewer_typestring"all_reviews""all_reviews" = every review. "avp_only_reviews" = verified purchase reviews only.
sort_bystring"recent""recent" = newest first. "" (empty) = the marketplace's "top reviews" ordering.
pagesintegerOptional. Scrape an exact number of review pages (19). When provided, it forces the paged mode and overrides all_reviews.
⚠️ Don't confuse the two "all_reviews". The all_reviews field (boolean) controls how many reviews are scraped. The value "all_reviews" for the reviewer_type field controls which reviewers are included. They are unrelated.

Pricing

ModeCost
Full history (all_reviews: true)$0.50 (or your custom rate)
Light scrape (all_reviews: false)$0.10 (or your custom rate)
Paged (pages: N)$0.02 for the first page + $0.01 per additional page (e.g. 3 pages = $0.04)

Examples

Basic — full review history (all defaults)
curl -X POST "https://amzapi.tagxdata.com/scrape" \
  -H "x-api-key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.example.com/dp/PRODUCTID"
  }'
Verified purchase reviews only, top-sorted
curl -X POST "https://amzapi.tagxdata.com/scrape" \
  -H "x-api-key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.example.com/dp/PRODUCTID",
    "reviewer_type": "avp_only_reviews",
    "sort_by": ""
  }'
Scrape exactly 3 pages of reviews
curl -X POST "https://amzapi.tagxdata.com/scrape" \
  -H "x-api-key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.example.com/dp/PRODUCTID",
    "pages": 3
  }'

Cost: $0.02 + 2 × $0.01 = $0.04

import requests, time

BASE = "https://amzapi.tagxdata.com"
headers = {"x-api-key": "your_api_key_here", "Content-Type": "application/json"}

# 1) Submit the job
resp = requests.post(f"{BASE}/scrape", headers=headers, json={
    "url": "https://www.example.com/dp/PRODUCTID",
    "all_reviews": True,
    "reviewer_type": "all_reviews",
    "sort_by": "recent",
})
request_id = resp.json()["request_id"]
print("Submitted:", request_id)

# 2) Poll until ready (202 = still processing, 200 = done)
while True:
    r = requests.get(f"{BASE}/result/{request_id}", headers=headers)
    if r.status_code == 202:
        time.sleep(5)
        continue
    r.raise_for_status()
    reviews = r.json()
    break

print(reviews)

Response

{
  "message": "Request accepted",
  "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

GET /result/{request_id}

Fetches the result of a previously submitted /scrape job. Poll this until it returns 200.

Status codes

CodeMeaning
200Done — the body contains the scraped review data.
202Still processing — wait and poll again.
403The job failed during processing. Credits were refunded.
404No job found for that request_id.

Example

curl -X GET "https://amzapi.tagxdata.com/result/550e8400-e29b-41d4-a716-446655440000" \
  -H "x-api-key: your_api_key_here"
import requests

request_id = "550e8400-e29b-41d4-a716-446655440000"
r = requests.get(
    f"https://amzapi.tagxdata.com/result/{request_id}",
    headers={"x-api-key": "your_api_key_here"},
)

if r.status_code == 202:
    print("Still processing, try again shortly.")
elif r.status_code == 200:
    print(r.json())   # review data

Response (200)

The body contains the scraped reviews for the product (structure depends on the request parameters).

Error Responses

Errors use standard HTTP status codes with a JSON body:

{
  "detail": "Error message description"
}
CodeMeaning
200OK — successful request with data.
202Accepted — job is still processing (poll again).
400Bad Request — invalid parameters (e.g. not a valid product URL, or pages outside 1–9).
401Unauthorized — invalid or missing API key.
402Payment Required — not enough credits.
403Forbidden — a reviews job failed during processing (credits refunded).
404Not Found — request_id does not exist.
502Bad Gateway — the product page could not be fetched from the source (e.g. blocked). The /pdp charge is refunded.
500Internal Server Error — unexpected error.