# Amazon Product Scraper API (`shakamize/amazon-product-scraper`) Actor

Scrape Amazon products from search, category and product URLs across 23 marketplaces. Pricing is localized to the delivery location you choose, so a ZIP code, a region or a whole country each return what a buyer there actually pays.

- **URL**: https://apify.com/shakamize/amazon-product-scraper.md
- **Developed by:** [Shakamize](https://apify.com/shakamize) (community)
- **Categories:** E-commerce
- **Stats:** 1 total users, 1 monthly users, 98.2% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $12.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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Amazon Product Scraper API

Scrape Amazon products from search results, category pages and product URLs.
Returns titles, prices, ratings, review counts, variants, offers and sellers as
structured JSON, CSV or Excel, across 23 Amazon marketplaces.

Pricing is localized to the delivery location you choose. Amazon charges
different prices in different places, so a ZIP code, a region or a whole country
each return what a buyer in that location would actually pay, in their own
currency.

### What people scrape Amazon product data for

- **Amazon price tracking and repricing** - watch what a product costs at a
  specific delivery address over time, in the currency a buyer there actually
  pays.
- **Competitor and market research on Amazon** - pull a whole search or
  category, with ratings, review counts and Amazon bestseller ranks.
- **ASIN catalogue enrichment** - turn a list of ASINs into full product data.
- **Buy box, offer and seller monitoring** - see who else is selling an item and
  at what price, including which seller currently holds the buy box.

### How to scrape Amazon prices by delivery address and ZIP code

Amazon does not have one price. It has a price per delivery location, and it
picks that location from wherever your request appears to come from. A scraper
that does not set the location explicitly reports whatever its exit node
implied - and often reports no price at all, because Amazon hides the buy box
for an address it cannot ship to.

Set `countryCode` and `zipCode` and the scraper performs Amazon's own delivery
address handshake before it reads a page, so every price is the price for that
address. Across a 40-product test spanning five categories, every product came back with
the requested location applied and a price attached.

Every result carries the location it was actually scraped under:

```json
"deliveryLocation": {
  "countryCode": "US", "zipCode": "10001",
  "city": "NEW YORK", "state": "NY", "applied": true
}
```

If `applied` is `false`, the price is whatever Amazon showed for the exit node's
own location rather than yours. It is never silently presented as the same
thing.

### How to scrape an Amazon search, category, product URL or bare ASIN

At minimum, one or more URLs:

```json
{
  "categoryOrProductUrls": [{ "url": "https://www.amazon.com/s?k=microsd+card" }],
  "maxItemsPerStartUrl": 100,
  "countryCode": "US",
  "zipCode": "10001"
}
```

Search URLs, category URLs and product URLs all work, and can be mixed. Bare
ASINs are accepted too.

#### Input reference for every Amazon scraper setting

| Field                                 | What it does                                                                    |
| ------------------------------------- | ------------------------------------------------------------------------------- |
| `categoryOrProductUrls`               | Search, category or product URLs. Required.                                     |
| `maxItemsPerStartUrl`                 | Stop after this many products per start URL.                                    |
| `maxSearchPagesPerStartUrl`           | How many listing pages to walk per start URL.                                   |
| `scrapeProductDetails`                | On by default. Off keeps listing-only fields, which is faster and billed lower. |
| `countryCode`                         | Delivery country. Changes prices and availability.                              |
| `zipCode`                             | Delivery postal code, for address-level pricing.                                |
| `locationDeliverableRoutes`           | Which page types the delivery location applies to.                              |
| `language`                            | Language to read Amazon in.                                                     |
| `proxyCountry`                        | Country to route requests through. Best left unset when using a ZIP code.       |
| `maxProductVariantsAsSeparateResults` | Scrape this many variants as full products of their own.                        |
| `scrapeProductVariantPrices`          | Emit a price for every variant.                                                 |
| `maxOffers`                           | Also collect competing offers per product.                                      |
| `scrapeSellers`                       | Attach seller details to each offer.                                            |
| `proxyConfiguration`                  | Proxy settings. Residential by default, which Amazon requires.                  |

### Amazon product data you get back, as JSON, CSV or Excel

One record per product, with price, list price, stars, review count, star
breakdown, variants, bestseller ranks and seller. This is a real result, not an
illustration:

```json
{
  "url": "https://www.amazon.com/dp/B0GC4J6CCC",
  "asin": "B0GC4J6CCC",
  "title": "NORTIV 8 Men's Trail Running Shoes Wide Toe Box",
  "brand": "NORTIV 8",
  "price": {
    "value": 63.99,
    "currency": "$",
    "currencyCode": "USD"
  },
  "listPrice": {
    "value": 69.99,
    "currency": "$",
    "currencyCode": "USD"
  },
  "inStock": true,
  "stars": 4.4,
  "reviewsCount": 1188,
  "starsBreakdown": {
    "5star": 0.7,
    "4star": 0.16,
    "3star": 0.07,
    "2star": 0.03,
    "1star": 0.04
  },
  "breadCrumbs": "Clothing, Shoes & Jewelry › Men › Shoes › Athletic › Running › Trail Running",
  "features": ["Breathable mesh upper with a wide toe box"],
  "variantAsins": ["B0FG2KH6BQ", "B0GC584NSB"],
  "variantAttributes": [
    {
      "key": "size_name",
      "label": "Size",
      "value": "11"
    },
    {
      "key": "color_name",
      "label": "Color",
      "value": "Dark Blue"
    }
  ],
  "bestsellerRanks": [
    {
      "category": "Clothing, Shoes & Jewelry",
      "rank": 10192
    }
  ],
  "seller": {
    "name": "topshoesUS",
    "id": "ABB9OQDQJ01FR"
  },
  "deliveryLocation": {
    "countryCode": "US",
    "zipCode": "10001",
    "city": "NEW YORK",
    "state": "NY",
    "applied": true
  },
  "locationText": "New York 10001",
  "countryCode": "US"
}
```

Variant prices and offers arrive as their own records, keyed by `parentAsin`.

A field that could not be read is `null`. It is never a zero, and never a value
borrowed from a neighbouring product on the page.

### Correctness: buy box prices, locale numbers and variant pricing

Three things this scraper is deliberately careful about, because they are the
common ways Amazon data comes back quietly wrong.

**Prices come only from the buy box.** A product page also carries prices for
recommended products in its carousels. A page-wide price selector picks one of
those up and reports it as the product's own price.

**Numbers are read in the locale that wrote them.** `36 704 évaluations` on
`amazon.fr` is 36,704 reviews, not 36. `Nr. 1.234` on `amazon.de` is rank 1234,
not rank 1. `48.6K` on a search card is 48,600, not 48. Separator handling is
decided from the number's own structure first and the marketplace only when the
number is genuinely ambiguous.

**Variant prices cannot take the product down with them.** Each variant price is
fetched as an independent request. A variant that fails to load costs you that
variant, not the parent product.

### Amazon product scraper pricing, pay per result

You are charged for results, not for runs or for time.

| Event                | Price   | What it is                                          |
| -------------------- | ------- | --------------------------------------------------- |
| Product              | $0.012  | One fully scraped product, including its price.     |
| Listing-only product | $0.002  | One product read from a listing without opening it. |
| Variant price        | $0.012  | One variant priced individually.                    |
| Offer                | $0.003  | One additional seller offer.                        |
| Seller               | $0.0015 | One seller profile attached to an offer.            |

**Setting a delivery location is not charged.** It is the part most likely to be
wrong elsewhere, so it is included rather than sold separately.

If you only need names, prices and ratings across a category, turn off
`scrapeProductDetails`: results then come from the listing pages at a fifth of
the price.

### Proxies for scraping Amazon without getting blocked

Use Apify residential proxy. Amazon serves an anti-bot interstitial to
unproxied traffic, and datacenter addresses are blocked after roughly one
request. Residential is the default in the input.

Leave the proxy country unset when you pass a `zipCode`. An exit inside the
marketplace's own country makes Amazon resolve a location of its own, and it
will then not hand over the token needed to change that location to yours. The
scraper handles this for you unless you override `proxyCountry` explicitly.

### Supported Amazon marketplaces, 23 countries

Australia, Belgium, Brazil, Canada, Egypt, France, Germany, India, Ireland,
Italy, Japan, Mexico, Netherlands, Poland, Saudi Arabia, Singapore, South
Africa, Spain, Sweden, Turkey, United Arab Emirates, United Kingdom, United
States.

### Errors: what happens when an Amazon URL cannot be scraped

A URL that cannot be scraped produces a record rather than disappearing:

```json
{
  "error": "product_not_found",
  "errorDescription": "Loaded a 404 page. The product does not exist.",
  "input": "https://www.amazon.com/dp/B0XXXXXXXX",
  "url": "https://www.amazon.com/dp/B0XXXXXXXX"
}
```

### Legal: public product data only, no personal data

This scraper collects publicly visible product information only. It does not
collect personal data, and it does not collect reviewer identities or review
text.

### Telemetry

The actor reports run health to its maintainer: error codes, the build number,
the marketplace domain, and per-field counts of how often a value was found.

When requests fail, it also sends a small, capped sample of the failures
themselves, so that a broken run can be diagnosed and fixed: the Amazon URL that
was requested, the HTTP status code that came back, and the error with its stack
trace. **That URL is the page you asked for, query string included.** It is not
personal data, but it is your input, and this section says so rather than leave
you to find out.

Your other input settings, your proxy configuration, and the scraped content
itself are never sent. Nothing at all is sent when a run is healthy.

# Actor input Schema

## `categoryOrProductUrls` (type: `array`):

Search result pages, category pages or product detail pages. Bare ASINs are accepted too. Example: https://www.amazon.com/s?k=microsd+card or https://www.amazon.com/dp/B09X7MPX8L

## `maxItemsPerStartUrl` (type: `integer`):

Stop after this many products for each start URL. Leave empty for no limit, which on a broad search means every page of results.

## `maxSearchPagesPerStartUrl` (type: `integer`):

How many pages of a search or category listing to walk before stopping.

## `scrapeProductDetails` (type: `boolean`):

On by default. Turn it off to keep only the summary fields shown on the listing page, which is faster and billed at the lower listing-only rate.

## `countryCode` (type: `string`):

The country to receive prices for. Amazon prices and availability depend on where the order would ship, so this changes the numbers you get back.

## `zipCode` (type: `string`):

A postal code within the delivery country, for prices that match a specific address. This is the setting that makes the scraped price match what a buyer at that address sees.

## `locationDeliverableRoutes` (type: `array`):

Which page types the delivery location is applied to. Applying it to fewer page types is faster.

## `language` (type: `string`):

Language to read Amazon in. Each marketplace supports a different set; an unsupported choice falls back to that marketplace default rather than failing.

## `proxyCountry` (type: `string`):

Country to route requests through. Leave on AUTO when using a ZIP code: an exit inside the marketplace country makes Amazon resolve its own location and refuse to hand over the token needed to change it.

## `maxProductVariantsAsSeparateResults` (type: `integer`):

Scrape this many variants of each product as full products of their own. 0 keeps only the parent.

## `scrapeProductVariantPrices` (type: `boolean`):

Emit a price for each variant of a product. Variant prices are fetched independently, so a variant that cannot be loaded never removes the parent product from your results.

## `maxOffers` (type: `integer`):

Also collect competing offers for each product. 0 collects none.

## `scrapeSellers` (type: `boolean`):

Attach seller information to each collected offer.

## `proxyConfiguration` (type: `object`):

Apify residential proxy is required in practice: Amazon serves an anti-bot interstitial to unproxied traffic and blocks datacenter addresses after roughly one request.

## Actor input object example

```json
{
  "categoryOrProductUrls": [
    "https://www.amazon.com/s?k=microsd+card"
  ],
  "maxItemsPerStartUrl": 50,
  "maxSearchPagesPerStartUrl": 9999,
  "scrapeProductDetails": true,
  "countryCode": "US",
  "zipCode": "10001",
  "locationDeliverableRoutes": [
    "PRODUCT",
    "SEARCH",
    "OFFERS"
  ],
  "proxyCountry": "AUTO_SELECT_PROXY_COUNTRY",
  "maxProductVariantsAsSeparateResults": 0,
  "scrapeProductVariantPrices": false,
  "maxOffers": 0,
  "scrapeSellers": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Every scraped product, with the price for the delivery address you requested.

# 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 = {
    "categoryOrProductUrls": [
        "https://www.amazon.com/s?k=microsd+card"
    ],
    "maxItemsPerStartUrl": 50,
    "countryCode": "US",
    "zipCode": "10001"
};

// Run the Actor and wait for it to finish
const run = await client.actor("shakamize/amazon-product-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 = {
    "categoryOrProductUrls": ["https://www.amazon.com/s?k=microsd+card"],
    "maxItemsPerStartUrl": 50,
    "countryCode": "US",
    "zipCode": "10001",
}

# Run the Actor and wait for it to finish
run = client.actor("shakamize/amazon-product-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 '{
  "categoryOrProductUrls": [
    "https://www.amazon.com/s?k=microsd+card"
  ],
  "maxItemsPerStartUrl": 50,
  "countryCode": "US",
  "zipCode": "10001"
}' |
apify call shakamize/amazon-product-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,shakamize/amazon-product-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/ao7BYrz9AxU58kBHa/builds/ik1Gz29KliJbl0gEu/openapi.json
