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

Extract Amazon product data from any search, category, or product URL across 24 marketplaces. Returns prices, ratings, specs, images, variants, all seller offers with Buy Box status, and seller business profiles. Set a delivery country for region-accurate pricing. 60+ fields per product.

- **URL**: https://apify.com/calm\_builder/amazon-product-scraper.md
- **Developed by:** [Coder](https://apify.com/calm_builder) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

Collect structured product data from [Amazon](https://www.amazon.com) using search URLs, category URLs, or direct product links. Paste the same links you use on the site and receive clean JSON records in your Apify dataset — prices, ratings, images, specifications, variations, and every seller offering the product.

Works across **24 Amazon marketplaces**. The marketplace is detected from each URL you paste, so a run can mix `amazon.com`, `amazon.de` and `amazon.co.jp` without any extra configuration.

Use it for **price monitoring**, **competitor research**, **Buy Box and repricing analysis**, **catalogue enrichment**, and **product sourcing**.

***

### What you get

Each saved row is **one product**, organized into clear sections:

| Section              | What it contains                                                                       |
| -------------------- | -------------------------------------------------------------------------------------- |
| **Identity**         | ASIN, title, brand, product URL, marketplace, and the input URL that produced the row  |
| **Pricing**          | Current price, list price, which source the price came from, and availability          |
| **Ratings**          | Star rating, review count, and the full 5/4/3/2/1 star breakdown                       |
| **Details**          | Description, feature bullets, specifications, category breadcrumbs, Best Sellers ranks |
| **Images**           | Thumbnail plus the full-size gallery                                                   |
| **`variants`**       | Sizes, colours and styles with the ASIN of each variation                              |
| **`offers`**         | Every seller on the listing — price, condition, delivery, who ships it                 |
| **`sellerProfiles`** | Registered business name, address and feedback for the sellers involved                |
| **Demand signals**   | "Bought in past month" counts, badges, sponsored flag                                  |

Results stream to the dataset as products are collected, so you can preview them before the run finishes.

***

### Quick start

1. Open the Actor in the Apify Console.
2. Paste one or more **Search and category URLs** — for example `https://www.amazon.com/s?k=laptop`.
3. Set **Products per URL** (default `20`). This applies to each URL separately.
4. Optionally turn on **Scrape product details** for the full product page data.
5. Click **Start**, then open the **Dataset** tab.

**How to get a search URL:** search on Amazon in your browser, apply any filters you want, then copy the URL from the address bar.

**Example input:**

```json
{
  "startUrls": [{ "url": "https://www.amazon.com/s?k=mechanical+keyboard" }],
  "maxItemsPerUrl": 50,
  "scrapeProductDetails": true
}
```

***

### Input parameters

#### Search and category URLs

One Amazon search or category link per row. Supported link types:

| Link type         | Example                                       |
| ----------------- | --------------------------------------------- |
| Keyword search    | `https://www.amazon.com/s?k=laptop`           |
| Department search | `https://www.amazon.com/s?k=tv&i=electronics` |
| Category results  | `https://www.amazon.com/s?rh=n%3A172282`      |

Some category links return an empty results page on Amazon itself. The scraper corrects these links automatically, so you still get products.

**Links that cannot be used:** Best Sellers and New Releases pages (`/gp/bestsellers/…`), department landing pages (`/b?node=…`), and brand storefronts (`/stores/…`). These pages do not contain a readable product list. To scrape a brand, search for it instead — `https://www.amazon.com/s?k=redragon` returns the same products. Unusable links are reported in the log and skipped; the rest of the run continues normally.

#### Products per URL

How many products to collect from **each** search or category URL, following pagination as needed. Default `20`. This does not apply to product URLs, where each link returns exactly one product.

#### Product URLs

Direct links to product pages (`/dp/…` or `/gp/product/…`), or bare ASINs. Each returns one fully detailed product. The product page is always opened for these, regardless of the **Scrape product details** setting.

#### Scrape product details

Opens each product's own page for what search results do not show: description, feature bullets, specifications, category breadcrumbs, Best Sellers ranks, the image gallery, availability, and the star rating breakdown.

Leave it off for a fast, low-cost run that returns titles, prices, images, ratings and review counts from the search results alone.

#### Offers, variants and sellers

| Setting                          | What it does                                                                                                               |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| **Scrape all seller offers**     | Returns every seller on the listing, not just the Buy Box winner — price, condition, delivery, and whether Amazon ships it |
| **Maximum offers per product**   | Caps offers per product. Default `10`; `0` returns all of them                                                             |
| **Scrape variants**              | Returns the product's other sizes, colours and styles with their ASINs                                                     |
| **Maximum variants per product** | Caps variations per product. Default `0`, which returns all of them                                                        |
| **Scrape seller profiles**       | Looks up the business behind each seller — registered name, address and feedback                                           |

Variants are read from the product page, so turning them on opens the product page even when **Scrape product details** is off.

Seller profiles are fetched once per seller and reused across every product that shares them.

#### Delivery location

Amazon shows different prices, availability and delivery estimates depending on where the order would ship.

| Setting                | What it does                                                                                   |
| ---------------------- | ---------------------------------------------------------------------------------------------- |
| **Deliver to country** | Any country Amazon ships to — it does not have to be the marketplace's own country             |
| **Postal code**        | Narrows the location further. Only used when the country matches the marketplace's own country |

Setting `amazon.com` to deliver to Pakistan, or `amazon.de` to Norway, shows the prices a shopper there would see. For destinations outside the marketplace's own country Amazon only accepts the country itself, so a postal code is ignored there. If a location cannot be applied, the run continues with Amazon's default and says so in the log.

***

### What you will see during a run

The log shows what is being collected and how far along it is:

```
Starting 2 search URL(s), up to 50 product(s) each.
Also collecting: product details, up to 10 offers per product.
Prices will be shown for delivery to 99501.
Searching amazon.com — up to 50 product(s).
Found 50 product(s).
Progress: 25 product(s) saved.
Finished. Saved 100 product(s).
```

Problems are reported in plain language as warnings — a link that could not be used, a URL that returned nothing, products whose details could not be retrieved — and the run continues with everything else. A run that hits a problem still finishes and keeps the results it collected, rather than discarding them.

***

### Output fields

#### Identity and source

| Field         | Description                                           |
| ------------- | ----------------------------------------------------- |
| `asin`        | Amazon's product ID                                   |
| `parentAsin`  | Parent product when this is one variation of a family |
| `title`       | Product title                                         |
| `brand`       | Brand name                                            |
| `url`         | Canonical product URL                                 |
| `marketplace` | Amazon domain the product came from, e.g. `amazon.de` |
| `inputUrl`    | The URL from your input that produced this row        |

#### Pricing and availability

| Field                        | Description                                                                                     |
| ---------------------------- | ----------------------------------------------------------------------------------------------- |
| `price`                      | Current price as displayed                                                                      |
| `listPrice`                  | Struck-through list price when shown                                                            |
| `priceSource`                | `buybox` when the price came from the Buy Box, `offer_listing` when it came from a seller offer |
| `availability`               | `in_stock`, `out_of_stock`, or `unknown`                                                        |
| `inStock` / `inStockText`    | Availability flag and Amazon's own wording                                                      |
| `hasBuyBox`                  | Whether the listing has a Buy Box winner                                                        |
| `fulfilledBy` / `sellerName` | Who ships and who sells the product                                                             |

A product with no Buy Box but live seller offers is reported as **in stock**, priced from the best available offer, with `priceSource` saying where the price came from — so the availability and the price never contradict each other.

#### Ratings

| Field                | Description                                            |
| -------------------- | ------------------------------------------------------ |
| `stars`              | Average star rating                                    |
| `reviewsCount`       | Number of ratings                                      |
| `starsBreakdown`     | Percentage of ratings at 5, 4, 3, 2 and 1 stars        |
| `hasRatingBreakdown` | Whether Amazon rendered the breakdown for this product |

Star rating and review count come from search results and are always present. The breakdown requires **Scrape product details**.

#### Product detail

| Field               | Description                                       |
| ------------------- | ------------------------------------------------- |
| `description`       | Product description text                          |
| `productOverview`   | The key/value overview table shown near the title |
| `attributes`        | The full technical specification table            |
| `features`          | Feature bullet list                               |
| `breadCrumbs`       | Category path                                     |
| `bestsellerRanks`   | Best Sellers ranks with their categories          |
| `images`            | Full-size image gallery                           |
| `thumbnailImage`    | Search-result thumbnail                           |
| `galleryThumbnails` | Thumbnail strip from the product gallery          |
| `videosCount`       | Number of videos on the listing                   |

#### Variants, offers and sellers

| Field                                        | Description                                                   |
| -------------------------------------------- | ------------------------------------------------------------- |
| `variants` / `variantAsins` / `variantCount` | Variations with their ASINs                                   |
| `variantDimensions` / `variantValues`        | Which attributes vary, such as size or colour                 |
| `offers` / `offersCount`                     | Every seller offer — price, condition, delivery, Buy Box flag |
| `sellerProfiles`                             | Business name, address and feedback for the sellers involved  |

#### Demand and status

| Field                        | Description                                                        |
| ---------------------------- | ------------------------------------------------------------------ |
| `boughtInPastMonth`          | Purchases in the past month, when Amazon shows it                  |
| `badge`                      | Badge text such as Amazon's Choice or Best Seller                  |
| `isSponsored`                | Whether the product appeared as a sponsored result                 |
| `isAmazonChoice`             | Whether the listing carries the Amazon's Choice badge              |
| `hasReviews` / `reviewsLink` | Whether reviews exist, and a link to them                          |
| `categoryPageData`           | Page number and position of the product within your search results |
| `delivery`                   | Delivery estimate shown for the active location                    |
| `visitStoreLink`             | Link to the brand's Amazon store, when there is one                |
| `scrapeErrors`               | Present only when part of a product could not be retrieved         |

Fields that depend on a setting you did not enable are absent rather than empty, so you can tell "not requested" apart from "not available".

***

### Example output

```json
{
  "asin": "B0GJTXVN9Z",
  "title": "Apple AirTag (2nd Generation)",
  "brand": "Apple",
  "url": "https://www.amazon.com/dp/B0GJTXVN9Z",
  "marketplace": "amazon.com",
  "price": "$79.99",
  "priceSource": "buybox",
  "availability": "in_stock",
  "hasBuyBox": true,
  "stars": 4.5,
  "reviewsCount": 10464,
  "starsBreakdown": { "5": 78, "4": 12, "3": 5, "2": 2, "1": 3 },
  "offersCount": 3,
  "variantCount": 2,
  "boughtInPastMonth": 20000,
  "inputUrl": "https://www.amazon.com/s?k=airtag"
}
```

***

### Free plan limits

Runs on the Apify free plan are limited to:

- **3** search or category URLs
- **5** product URLs
- **20** products per URL

Every feature is available on the free plan — offers, variants, seller profiles and delivery location all work; only the number of products is capped. Upgrade to a paid plan to remove the limits.

***

### Tips for best results

- **Filter on Amazon, not afterwards.** Set price ranges, brands, ratings and Prime filters in your browser, then copy the finished URL. Amazon does the filtering and you collect fewer, better rows.
- **Start small.** Run with **Products per URL** set to 5 and details on, check the fields you care about, then scale up.
- **Turn on only what you need.** Product details, offers and seller profiles each add work per product. A price-tracking run usually needs none of them.
- **Set a delivery location for price accuracy.** Prices vary by region; without a location Amazon picks one for you.
- **Use several narrow searches instead of one broad one.** Amazon caps how deep any single search can be paginated, so three targeted searches return more than one generic search.

***

### Frequently asked questions

**Which marketplaces are supported?**
All 24: `amazon.com`, `.co.uk`, `.de`, `.fr`, `.it`, `.es`, `.ca`, `.co.jp`, `.in`, `.com.au`, `.com.mx`, `.com.br`, `.nl`, `.se`, `.pl`, `.com.be`, `.ie`, `.com.tr`, `.ae`, `.sa`, `.eg`, `.sg`, `.co.za`, and `.cn`. Just paste a URL from any of them.

**Can I mix marketplaces in one run?**
Yes. Each URL is handled on its own marketplace, and every row records which one it came from.

**Why did a category URL return nothing?**
Some Amazon category links load an empty results page. The scraper repairs these automatically. If a link still returns nothing, open it in your browser — if it shows no products there either, copy the URL from a working results page instead.

**Why are Best Sellers pages not supported?**
Those pages do not include a readable product list. Searching for the same category returns the products with full data.

**Do I get reviews?**
You get the star rating, the number of ratings, and the 5/4/3/2/1 breakdown. Individual review text is not included.

**Will prices match what I see?**
Prices are what Amazon shows for the delivery location in use. Set **Deliver to country** (and a postal code where it applies) to match the region you are comparing against.

**Are sponsored products included?**
Yes, flagged with `isSponsored` so you can filter them out.

***

### Support

Found a problem or need a field that is not here? Open an issue on the Actor's **Issues** tab with the input you used and what you expected, and it will be looked at.

# Actor input Schema

## `startUrls` (type: `array`):

One Amazon **search or category** URL per row.

Supported links:

- Keyword search — `https://www.amazon.com/s?k=laptop`
- Department search — `https://www.amazon.com/s?k=tv&i=electronics`
- Category results — `https://www.amazon.com/s?rh=n%3A172282`

Some category links return an empty results page on Amazon; the scraper repairs the link before fetching, so you still get products.

**Not supported:** Best Sellers pages (`/gp/bestsellers/...`), department landing pages (`/b?node=...`) and brand storefronts (`/stores/...`) — these pages carry no product list. To scrape a brand, search for it instead: `https://www.amazon.com/s?k=redragon`.

## `maxItemsPerUrl` (type: `integer`):

How many products to collect from **each** search or category URL. The scraper follows pagination until it reaches this number or runs out of results.

Does not apply to **Product URLs**, where every link returns exactly one product.

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

Open each product's own page for the fields a listing page does not show: full description, product specifications, Best Sellers rank, availability, and the 5/4/3/2/1 star rating breakdown.

Leave this off for a faster, cheaper run that returns titles, prices, images, ratings and review counts from the listing page only.

Each product page opened is billed as one **product detail** event.

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

One Amazon **product page** URL per row (`/dp/...` or `/gp/product/...`).

Each link returns exactly one product with full details — **Products per URL** does not apply here, and the product page is **always** opened, so every product is billed as a **product detail** event.

## `scrapeOffers` (type: `boolean`):

Collect every seller offering the product, not only the Buy Box winner — each offer's price, condition, delivery, and whether it is sold or shipped by Amazon.

Useful for Buy Box tracking, repricing, and counting competitors on a listing.

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

Caps how many seller offers are returned per product. Set **0** to return every offer available.

Offers are charged per offer returned, so a popular product with dozens of sellers costs more at **0** than at a set limit. The default of 10 covers the Buy Box winner and the main competing sellers.

Applies only when **Scrape all seller offers** is on.

## `scrapeVariants` (type: `boolean`):

Collect the product's other variations — sizes, colours, styles — with the ASIN of each one.

Variants are read from the product page, so turning this on opens the product page even when **Scrape product details** is off, and the product is billed as a **product detail** event.

## `maxVariants` (type: `integer`):

Caps how many variations are returned per product. Set **0** to return all of them.

Applies only when **Scrape variants** is on. This limits the output only — it does not change how many requests the run makes.

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

Look up the business behind each seller — registered business name, address and contact details where Amazon publishes them, plus the seller's feedback rating.

Profiles are fetched once per seller and reused across every product that shares them, so you are charged once for a seller no matter how many of your products they sell.

Turn on **Scrape all seller offers** as well to get a profile for every seller on a listing, not just the one winning the Buy Box.

## `deliveryCountry` (type: `string`):

Prices, availability and delivery estimates change with the delivery address. Choose the country to see prices for, or leave it on **Amazon default** to use whatever Amazon shows.

This can be **any** country Amazon ships to — it does not have to be the marketplace's own country. Setting `amazon.com` to deliver to Pakistan, or `amazon.de` to Norway, shows the prices and availability a shopper there would see.

Countries that are also Amazon marketplaces are marked with their domain. If Amazon does not ship to the country you pick, the run continues with the default location and records it in the log.

## `deliveryPostalCode` (type: `string`):

Optional, and only used when the country you picked is the marketplace's **own** country — a ZIP on `amazon.com` while delivering to the United States, for example `99501`.

Amazon narrows prices and delivery estimates to that postal code. For any other country it only accepts the country itself, so a postal code here is ignored.

Examples: `99501` (United States), `10115` (Germany), `EC1A 1BB` (United Kingdom).

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.amazon.com/s?k=laptop"
    }
  ],
  "maxItemsPerUrl": 20,
  "scrapeProductDetails": false,
  "productUrls": [
    {
      "url": "https://www.amazon.com/dp/B0CDWP1D58"
    }
  ],
  "scrapeOffers": false,
  "maxOffers": 10,
  "scrapeVariants": false,
  "maxVariants": 0,
  "scrapeSellers": false,
  "deliveryCountry": ""
}
```

# Actor output Schema

## `results` (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 = {
    "startUrls": [
        {
            "url": "https://www.amazon.com/s?k=laptop"
        }
    ],
    "productUrls": [
        {
            "url": "https://www.amazon.com/dp/B0CDWP1D58"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("calm_builder/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 = {
    "startUrls": [{ "url": "https://www.amazon.com/s?k=laptop" }],
    "productUrls": [{ "url": "https://www.amazon.com/dp/B0CDWP1D58" }],
}

# Run the Actor and wait for it to finish
run = client.actor("calm_builder/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 '{
  "startUrls": [
    {
      "url": "https://www.amazon.com/s?k=laptop"
    }
  ],
  "productUrls": [
    {
      "url": "https://www.amazon.com/dp/B0CDWP1D58"
    }
  ]
}' |
apify call calm_builder/amazon-product-scraper --silent --output-dataset

```

## MCP server setup

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