# Amazon Product Scraper — Prices, Sellers & Ranks (`astravalabs/amazon-products-scraper`) Actor

Turn Amazon ASINs or product URLs from amazon.com and amazon.co.uk into 46-field records: price, discount, stock, seller and fulfilment, offers, rating, reviews, bought-in-past-month, best-seller ranks, specs and images. Pay only for products collected.

- **URL**: https://apify.com/astravalabs/amazon-products-scraper.md
- **Developed by:** [astravalabs](https://apify.com/astravalabs) (community)
- **Categories:** E-commerce, Automation, AI
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 products

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Amazon Product Scraper (US & UK)

Turn Amazon ASINs or product URLs from amazon.com or amazon.co.uk into
structured product records.

> **Unofficial tool:** This Actor is independently developed and is not
> affiliated with, endorsed by, or sponsored by Amazon. Amazon names and
> trademarks belong to their respective owners.

Built for price monitoring, catalog enrichment, competitor tracking and
market research where a missing or wrong row costs more than the row itself:

- **Reliable.** 418 of 420 products collected in our launch validation runs
  on amazon.com and amazon.co.uk; the two misses were proxy connection
  failures, which now get extra retries. Blocked pages are retried on fresh
  identities, and you are never charged for a product that could not be
  collected.
- **Correct, not just complete.** A page Amazon serves in another country's
  currency is detected and retried rather than stored as if it were local.
  Titles, ratings and review counts were cross-checked against Amazon's search
  results for 300 products and matched wherever both showed a value.
- **46 fields per product:** price and list price, discount, coupon, stock,
  seller and fulfilment, competing offers, rating and review count, "bought
  in past month", best-seller ranks, category path, feature bullets,
  specifications, images and variations.
- **US and UK.** Paste amazon.com or amazon.co.uk links, or bare ASINs.

### Pricing

**$4.00 per 1,000 products** ($0.004 per product), plus a negligible Actor
start fee. You pay only for products in the dataset: products that could not
be collected, and skipped or duplicate inputs, are never charged.

### Need to discover products first?

Use the Amazon Search Results Scraper to search by keyword, then pass its `asin`
or `url` values into this Actor's `productUrls` input.

### Input

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `productUrls` | string array | **required** | One to 1,000 entries. Each may be a bare ASIN (`B0DXPFKQXL`) or an Amazon US or UK product URL. |
| `products` | object array | none | Additional entries containing `asin` or `url`, plus an optional search `referrer`. |
| `marketplace` | string | `AUTO` | `AUTO` uses the store of the first product URL, or amazon.com when only bare ASINs are given. `US` or `UK` forces a store; entries for the other store are skipped and reported. |

`productUrls` is required and must contain at least one entry. The Actor never
invents a product when input is empty — it fails immediately, before any
network work.

Bare ASINs are accepted because ASINs, not URLs, are Amazon's natural product
identifier. Titled slugs, `ref=` tracking, and other query parameters are
stripped: every entry normalizes to `<marketplace origin>/dp/<ASIN>`.

Amazon variations are themselves distinct ASINs, so there is no separate
variant field — request the child ASIN directly.

#### Unusable entries are skipped, not fatal

Entries containing no ASIN — most commonly Amazon's sponsored `/sspa/click`
search redirects, which can be roughly one in ten of a scraped result set — are
skipped and reported in `RUN_REPORT.skippedInputs` with their input position
and reason. Duplicates are reported the same way. One bad entry in a
1,000-product list therefore costs that entry, not the run.

The run fails only when no supplied entry is usable at all.

```json
{
  "productUrls": ["B0C3HCD34R", "https://www.amazon.com/dp/B07WCV632L"]
}
```

With `marketplace` left on `AUTO`, this run uses amazon.com: the first URL is
an amazon.com link. Paste amazon.co.uk links, or set `"marketplace": "UK"`,
for the UK store.

### Output

One dataset row per validated product. Optional fields are `null` or empty when
Amazon does not display a reliable value.

```json
{
  "marketplace": "UK",
  "asin": "B0DXPFKQXL",
  "parentAsin": null,
  "url": "https://www.amazon.co.uk/dp/B0DXPFKQXL",
  "title": "Rii Mechanical Keyboard Full Size, RGB Wired Gaming Keyboard",
  "brand": "Rii",
  "author": null,
  "listingStatus": "ACTIVE",
  "availabilityText": "In stock",
  "inStock": true,
  "stockRemaining": null,
  "displayedPrice": 27.98,
  "displayedPriceText": "£27.98",
  "listPrice": 29.98,
  "discountPercent": 6.7,
  "unitPriceText": null,
  "currency": "GBP",
  "rating": 4.4,
  "reviewCount": 24,
  "boughtPastMonthText": "50+ bought in past month",
  "boughtPastMonthLowerBound": 50,
  "soldBy": "Boomtek UK",
  "shipsFrom": "Amazon",
  "offerCount": 2,
  "offerCountText": "New (2)",
  "offerCondition": "NEW",
  "lowestOfferPrice": 27.98,
  "lowestNewPrice": 27.98,
  "categoryPath": ["Computers & Accessories", "Accessories", "Keyboards"],
  "bestSellersRank": [{"rank": 6415, "category": "Computers & Accessories"}],
  "featureBullets": ["..."],
  "productDetails": {"Brand": "Rii", "Connectivity technology": "USB-A"},
  "imageUrls": ["https://m.media-amazon.com/images/I/..."],
  "variationDimensions": ["color_name"],
  "variantCount": 5,
  "selectedVariation": ["black / black"],
  "collectedAt": "2026-08-11T12:37:01+00:00"
}
```

| Group | Fields |
| --- | --- |
| Identity | `asin`, `parentAsin`, `title`, `brand`, `author`, `url`, `marketplace` |
| Price | `displayedPrice`, `listPrice`, `discountPercent`, `unitPriceText`, `couponText`, `currency` |
| Availability | `listingStatus`, `availabilityText`, `inStock`, `stockRemaining` |
| Offer | `soldBy`, `shipsFrom`, `deliveryText`, `offerCount`, `offerCountText`, `offerCondition`, `lowestOfferPrice`, `lowestNewPrice` |
| Demand | `rating`, `reviewCount`, `boughtPastMonth*`, `bestSellersRank` |
| Catalog | `categoryPath`, `productDetails`, `productDetailsList`, `featureBullets`, `descriptionText`, `hasAPlusContent` |
| Media | `mainImageUrl`, `imageUrls`, `hasVideo` |
| Variations | `variationDimensions`, `variationAsins`, `variantCount`, `selectedVariation` |

`productDetails` is a JSON object whose keys differ by category. The equivalent
`productDetailsList` repeats those attributes as ordered `{"name", "value"}`
objects so dynamic keys survive CSV and spreadsheet export.

Amazon variations are distinct ASINs, so `variationAsins` maps each sibling
ASIN to its dimension values — feed those ASINs back in to collect them.

Products that are currently unavailable still produce a row, marked
`listingStatus: "UNAVAILABLE"`. Blocked, missing, mismatched, and unrecognized
pages never enter the dataset; they are reported in `RUN_REPORT`.

#### Data semantics

- Prices, availability, and delivery text are what Amazon displayed at
  collection time to a visitor in that store's country (US or UK). They are
  not universal seller policy.
- For products with variations, the price is that of the variation Amazon
  selects by default on the product page; search results may show a different
  variation's price.
- When no seller wins the buy box, `soldBy` is empty and the displayed price
  is the one Amazon shows for the other buying options.
- `listPrice` is populated only when Amazon shows a strike-through above the
  current price; a "was" price at or below it is discarded rather than guessed.
- Book pages reuse the byline for author and format, so media products
  populate `author` and leave `brand` empty.
- The Actor does not download images. It returns ordered, deduplicated links
  to the full-size images Amazon displays.
- `offerCount` counts the competing offers Amazon summarises on the product
  page, and `offerCondition` states what that count covers. Amazon writes
  either "New (2) from £27.98" or "New & Used (5) from £16.99", and these do
  not mean the same thing, so `lowestNewPrice` is populated only when the
  summary is unambiguously new-only.
- `offerCount` distinguishes zero from unknown. Amazon renders the offer
  container even when nothing competes, so an empty container reports `0`,
  a real "nobody else is selling this". A missing container, or wording the
  parser does not recognise, reports `null` — unknown, not zero.
- `shipsFrom` and `soldBy` are equal when Amazon shows a combined
  "Shipper / Seller" block, which is how it presents a single party filling
  both roles. They differ when fulfilment and selling are split, which is the
  signal for Amazon-fulfilled versus merchant-fulfilled.
- A per-seller breakdown, including which offers are fulfilled by Amazon, is
  not on the product page and would need a second request per product. It is
  out of scope.

### Run reports

`RUN_REPORT` records per-product attempts and outcomes, skipped input entries,
session creation and rotation counts, response bytes, timing, per-field
coverage, dataset write stats, and cost estimates. `RUN_PROGRESS` is
checkpointed during the run.

Because Amazon product templates vary by category, `fieldCoverage` is reported
explicitly — silent extraction gaps are the likeliest failure mode.

### How it collects

No login, CAPTCHA solving, or access-control circumvention. Public product
pages only.

Each worker opens a fresh residential identity in the store's country,
clones it into independent HTTP clients, and fetches several products
concurrently. There is no warmup request: a live spike measured homepage
warmups challenged on 10 of 10 attempts, while cold product fetches succeeded
99.2% of the time. A product is retried up to three times on fresh identities
when Amazon challenges the page or serves it for another country, with three
further attempts reserved for proxy connection failures.

### Responsible use

This Actor collects publicly available information. You are responsible for
ensuring your use of the data complies with Amazon's terms, applicable laws,
privacy rules, intellectual-property rights, and any contractual obligations.

# Actor input Schema

## `productUrls` (type: `array`):

One to 1,000 Amazon UK products. Each entry may be a bare ASIN (B0DXPFKQXL) or any Amazon UK product URL. Entries that contain no ASIN, such as sponsored /sspa/click links, are skipped and reported in RUN_REPORT rather than failing the run.

## `products` (type: `array`):

Advanced JSON input for listings-scraper enrichment. Each entry accepts an ASIN or URL plus the originating search page.

## `marketplace` (type: `string`):

Which Amazon store to collect from. Auto uses the store of the first product URL, or amazon.com when you paste only ASINs. Prices are returned in that store's currency.

## Actor input object example

```json
{
  "productUrls": [
    "B0DXPFKQXL"
  ],
  "marketplace": "AUTO"
}
```

# Actor output Schema

## `products` (type: `string`):

No description

## `runReport` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "productUrls": [
        "B0DXPFKQXL"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("astravalabs/amazon-products-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "productUrls": ["B0DXPFKQXL"] }

# Run the Actor and wait for it to finish
run = client.actor("astravalabs/amazon-products-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "productUrls": [
    "B0DXPFKQXL"
  ]
}' |
apify call astravalabs/amazon-products-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,astravalabs/amazon-products-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/1EDoYzPTb5asTQDar/builds/k6jizHAxi3CaBmBR2/openapi.json
