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

Scrape Amazon product listings and extract structured product data including titles, prices, ratings, reviews, availability, product URLs, images, and other product details. Search by keyword and collect product data for price monitoring, product research, market analysis, and e-commerce automation.

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

## Pricing

from $0.50 / 1,000 results

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

### What does Amazon Product Scraper do?

**Amazon Product Scraper** extracts product data from [Amazon.com](https://www.amazon.com) - keyword search results and full product detail pages - **anonymously, no login, no Amazon account, no API key**. Two operations live in one actor: search for products by keyword (optionally narrowed to a category), or look up full detail for one or many ASINs.

### Why use this Actor?

- **Price tracking** - schedule `productDetails` on a cron and diff consecutive runs to catch price drops and restocks.
- **Market research / assortment mapping** - `search` gives you ranked results for any keyword, with price, rating, review count, and Amazon's Choice / Best Seller badges.
- **Batch, one start fee** - pass a list of keywords or ASINs and one run covers all of them.

### How to use it

1. Pick an **Operation**: Product Search or Product Details.
2. Fill the matching field:
   - **Search** → `query` (e.g. `coffee maker`) or `queries` for a batch. Optionally add `categoryId` to narrow results to one category - see the note below, a category ID only works together with a query.
   - **Product Details** → `asin` (e.g. `B01GJOMWVA`) or a full product URL, or `asins` for a batch.
3. Optionally set `sortBy` or price filters.
4. Click **Start**.

There is no page cap on `search` - it always follows a query through to Amazon's own last reported page. Batch a lot of keywords and this can produce a very large run; that's intentional, not a bug.

Batch fields (`queries`/`asins`) win over their singular counterparts when filled; duplicates and blanks are dropped automatically.

### Input

| Field                        | Type              | Description                                                                                                                         |
| ---------------------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `operation`                  | string (required) | One of: `search`, `productDetails`.                                                                                                 |
| `query` / `queries`          | string / array    | Search keyword(s). Required by `search`.                                                                                            |
| `categoryId` / `categoryIds` | string / array    | Amazon browse-node ID(s) to narrow a search - must be combined with a query, see [Category filtering](#category-filtering) below.   |
| `asin` / `asins`             | string / array    | An ASIN (e.g. `B01GJOMWVA`) or a full product URL. Used by `productDetails`.                                                        |
| `sortBy`                     | string            | `relevance`, `price-asc-rank`, `price-desc-rank`, `review-rank`, `date-desc-rank`. Applies to `search`.                             |
| `minPrice` / `maxPrice`      | integer           | Price filters. Applies to `search` - see the caveat below.                                                                          |
| `zipCode`                    | string            | Delivery ZIP code the Actor sets automatically before crawling - see [Why a ZIP code?](#why-a-zip-code) below. Defaults to `10001`. |
| `proxyConfiguration`         | object            | A residential proxy is strongly recommended for sustained volume - Amazon rate-limits repeated traffic from one IP.                 |

### Why a ZIP code?

A cookie-less request to Amazon renders a degraded page where almost every result shows "No featured offers available / See options" instead of a real price - Amazon withholds pricing until a delivery location is set, exactly like it does for a real visitor's first page load. Before crawling, this Actor automatically runs the same two calls a browser makes when you first pick a delivery location (load the homepage, then post the ZIP code to Amazon's address-change endpoint) and reuses the resulting session for every request. Live-verified: 47 of 48 results priceless before this step, 0 of 48 after.

### Category filtering

A category ID (`rh=n:{id}` in Amazon's own URLs) only narrows an existing keyword search - live-verified: the same node ID with no keyword renders Amazon's generic homepage (0 results), while adding it alongside a keyword genuinely narrows the result set (a 48-result search dropped to 26 with a real category ID added, and to 33 with a different node). Find a node ID from the number after `node=` in any Amazon category page's URL.

### Output

One flat row per item. Search rows carry search-result fields; product-detail rows carry the full page. Every row has `_operation` (which mode produced it) and `status` (`success` or `error`) so you can split/filter a mixed export.

Search row example:

```json
{
    "_operation": "search",
    "asin": "B01GJOMWVA",
    "title": "BLACK+DECKER 12-Cup Drip Coffee Maker with Vortex Brewing",
    "price": 31.97,
    "listPrice": null,
    "currency": "USD",
    "rating": 4.4,
    "reviewCount": 50181,
    "image": "https://m.media-amazon.com/images/I/61Rdl5C2AHL.jpg",
    "productUrl": "https://www.amazon.com/BLACK-DECKER-Programmable-Coffeemaker/dp/B01GJOMWVA",
    "isSponsored": false,
    "isAmazonChoice": true,
    "isBestSeller": false,
    "query": "coffee maker",
    "status": "success"
}
```

Product detail row example:

```json
{
    "_operation": "productDetails",
    "asin": "B01GJOMWVA",
    "title": "BLACK+DECKER 12-Cup Drip Coffee Maker with Vortex Brewing",
    "brand": "BLACK+DECKER",
    "price": 31.97,
    "listPrice": 34.99,
    "currency": "USD",
    "rating": 4.4,
    "reviewCount": 50181,
    "availability": "In Stock",
    "outOfStock": false,
    "features": ["12-CUP DURALIFE GLASS CARAFE: ...", "SNEAK-A-CUP FEATURE TO PREVENT DRIPS: ..."],
    "images": ["https://m.media-amazon.com/images/I/41QB48wA6UL.jpg"],
    "categories": ["Home & Kitchen", "Kitchen & Dining", "Coffee, Tea & Espresso", "Coffee Makers"],
    "productUrl": "https://www.amazon.com/dp/B01GJOMWVA",
    "status": "success"
}
```

### Pricing

This Actor uses pay-per-event pricing - one small run-start charge, then a per-row charge for each search result or product-detail lookup. See the **Pricing** tab for current rates. Failed lookups land as `status: "error"` rows and are never charged. There is no page cap or result cap - `search` always runs to Amazon's own last reported page for each keyword, so keep your batch size (number of keywords/ASINs) in mind to bound spend on a given run.

### Limitations

- Only the numbers/text Amazon shows to an anonymous, logged-out visitor are available.
- Customer reviews are not part of this Actor - see the companion **Amazon Review Scraper** for the top reviews shown on each product page.
- `sortBy`/`minPrice`/`maxPrice` ride on Amazon's `rh`/`s` query params, which are community-documented and long-stable but were not independently differential-verified live in this session the way keyword search, category narrowing, and product detail were.
- US marketplace (`amazon.com`) only in this version.
- Amazon's page markup drifts over time; the extraction code targets stable, semantic selectors (`#productTitle`, `.po-brand`, `data-component-type="s-search-result"`, etc.) but a large redesign may need an update.

### FAQ

**Does Amazon have a public API?** The Product Advertising API exists but requires an active Associates account with qualifying sales and is scoped to affiliate use cases, not general scraping. This Actor gets you search and product data anonymously, no approval process.

**Do I need an Amazon account or API key?** No - it runs entirely against Amazon's public, logged-out web pages.

**Why does `categoryId` alone return nothing?** By design - see [Category filtering](#category-filtering) above. Combine it with a `query`.

**A run returns 0 results with no error - why?** An unusually narrow keyword/category/price combination can legitimately return nothing, or a run mid-way through a large batch can occasionally hit a rate-limited session - a residential proxy and Amazon's own retry-friendly page structure handle this automatically in most cases.

### Disclaimer

This Actor is an independent tool, not affiliated with or endorsed by Amazon.com, Inc. It only accesses data Amazon serves publicly to anonymous visitors. Use it in compliance with Amazon's Conditions of Use and applicable law in your jurisdiction. Found a bug or have a feature request? Use the Issues tab on this Actor's page.

# Actor input Schema

## `operation` (type: `string`):

Which Amazon data to scrape. One operation per run.

## `query` (type: `string`):

Keyword to search Amazon, e.g. "coffee maker". Used by the search operation. Defaults to a demo query if left blank.

## `queries` (type: `array`):

Many keywords in one run. Wins over "query" when filled. Duplicates and blanks are dropped.

## `categoryId` (type: `string`):

An Amazon browse-node ID to narrow a search to one category, e.g. "172282". Must be combined with "query" - a category ID alone (no keyword) does not return results. Find a node ID from an Amazon category page's URL (the number after "node=").

## `categoryIds` (type: `array`):

Many browse-node IDs in one run. Wins over "categoryId" when filled.

## `asin` (type: `string`):

An Amazon ASIN (e.g. "B098CHH298") or a full product URL. Used by the productDetails operation. Defaults to a demo product if left blank.

## `asins` (type: `array`):

Many ASINs or product URLs in one run. Wins over "asin" when filled.

## `domain` (type: `string`):

Which Amazon marketplace to query.

## `sortBy` (type: `string`):

Applies to search.

## `minPrice` (type: `integer`):

Applies to search.

## `maxPrice` (type: `integer`):

Applies to search.

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

Amazon shows a degraded page with no real prices ("See options" only) until a delivery location is set. The Actor sets this automatically before crawling - change it if you need pricing/availability for a specific US region.

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

A residential proxy is strongly recommended for sustained volume - Amazon rate-limits repeated traffic from one IP.

## Actor input object example

```json
{
  "operation": "search",
  "query": "coffee maker",
  "asin": "B01GJOMWVA",
  "domain": "amazon.com",
  "zipCode": "10001",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `overview` (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 = {
    "query": "coffee maker",
    "asin": "B01GJOMWVA"
};

// Run the Actor and wait for it to finish
const run = await client.actor("mrdoe/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 = {
    "query": "coffee maker",
    "asin": "B01GJOMWVA",
}

# Run the Actor and wait for it to finish
run = client.actor("mrdoe/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 '{
  "query": "coffee maker",
  "asin": "B01GJOMWVA"
}' |
apify call mrdoe/amazon-product-scraper --silent --output-dataset

```

## MCP server setup

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