# Amazon Reviews Scraper (Pay-Per-Event) (`prodiger/amazon-reviews-scraper`) Actor

Scrape written Amazon.com product reviews without a login or browser. Returns numeric ratings, exact ISO dates, review text, helpful votes, images, videos, verified/Vine flags, local rating and keyword filters, and run-level deduplication. Reviewer names are redacted unless explicitly enabled.

- **URL**: https://apify.com/prodiger/amazon-reviews-scraper.md
- **Developed by:** [Arnas](https://apify.com/prodiger) (community)
- **Categories:** E-commerce, AI, Automation
- **Stats:** 7 total users, 4 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 reviews

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 Reviews Scraper

Scrape written Amazon.com product reviews without an Amazon login, browser
automation, or residential proxy. The Actor returns analysis-ready review
text, numeric ratings, exact ISO dates, helpful votes, images, videos,
verified-purchase and Vine flags, and transparent source metadata.

Results stream to an Apify dataset and can be downloaded as JSON, CSV, Excel,
or consumed through the API.

### Why use this Actor?

- **Hundreds of written reviews over plain HTTP.** The Actor uses Woot's public
  Amazon review JSON feed. Unlimited runs combine rating and sort passes, then
  deduplicate overlaps.
- **Correct dates and ratings.** `ratingScore` is numeric. `date` is normalized
  to ISO 8601 while `reviewedIn` preserves Amazon's original date/location text.
- **No silent incomplete success.** Invalid inputs, products with no matching
  reviews, and partial transport failures receive structured, non-billable
  diagnostic rows.
- **No duplicate billing.** A stable SHA-256 `reviewFingerprint` prevents the
  same written review from being written or charged twice across overlapping
  passes.
- **Dataset and billing commit together.** Review rows use Apify's event-aware
  dataset write; filtering and deduplication happen before billing admission.
- **Privacy-safe defaults.** Reviewer names are `null` unless
  `includeGdprSensitive` is explicitly enabled. The source does not expose
  profile IDs, profile links, or avatars, so those fields remain `null`.
- **Local filters.** Rating groups, keyword OR matching, and absolute or
  relative date cutoffs are applied before a row is written.

### Quick start

1. Add one or more Amazon.com product URLs.
2. Choose a review limit and optional filters.
3. Click **Start**.

Example input:

```json
{
  "productUrls": [{ "url": "https://www.amazon.com/dp/B0CWXNS552" }],
  "maxReviews": 100,
  "sort": "recent",
  "filterByRatings": ["critical"],
  "reviewsFilterByKeywords": ["battery", "quality"],
  "reviewsCutoffDate": "6 months",
  "includeGdprSensitive": false
}
```

Direct 10-character ASIN strings are also accepted when starting the Actor
through the API.

### Input reference

| Field                     |    Default | Description                                                                                                   |
| ------------------------- | ---------: | ------------------------------------------------------------------------------------------------------------- |
| `productUrls`             |   required | Amazon.com product or product-review URLs.                                                                    |
| `maxReviews`              |      `100` | Unique written reviews per product. `0` scans every available source pass.                                    |
| `includeGdprSensitive`    |    `false` | Include reviewer display names.                                                                               |
| `sort`                    |  `helpful` | Primary source order: `helpful` or `recent`.                                                                  |
| `reviewsCutoffDate`       |          — | UTC cutoff as `YYYY-MM-DD`, ISO timestamp, or relative time such as `2 weeks`.                                |
| `filterByRatings`         | `allStars` | One or more of `allStars`, `fiveStar`, `fourStar`, `threeStar`, `twoStar`, `oneStar`, `positive`, `critical`. |
| `reviewsFilterByKeywords` |          — | Case-insensitive OR match against title and body.                                                             |
| `maxRequestRetries`       |        `3` | Retries per transient or malformed upstream response (1–10).                                                  |
| `maxConcurrency`          |        `5` | Concurrent HTTP requests (1–20); the run is also capped at 120 requests/minute.                               |
| `proxyConfiguration`      |          — | Optional escape hatch; normally unnecessary.                                                                  |

The hidden compatibility inputs `reviewsUseProductVariantFilter`,
`scrapeProductDetails`, `reviewsAlwaysSaveCategoryData`, and
`deduplicateRedirectedAsins` are accepted. See **Current limitations** for
their exact behavior.

### Output example

```json
{
  "productAsin": "B0CWXNS552",
  "productOriginalAsin": "B0CWXNS552",
  "variantAsin": "B0CWXNS552",
  "ratingScore": 4,
  "reviewTitle": "Works and lasts",
  "reviewDescription": "Accurate tracking and good battery life.",
  "date": "2026-08-13T00:00:00.000Z",
  "reviewedIn": "Reviewed in the United States on August 13, 2026",
  "country": "United States",
  "countryCode": "US",
  "isVerified": true,
  "isAmazonVine": false,
  "reviewId": null,
  "reviewFingerprint": "f0b5...64-character-sha256...",
  "reviewUrl": null,
  "reviewReaction": "2 people found this helpful",
  "reviewImages": [],
  "reviewVideos": [],
  "username": null,
  "userId": null,
  "userProfileLink": null,
  "avatar": null,
  "position": 1,
  "filterByRating": "allStars",
  "filterByKeyword": "battery",
  "foundNoReviews": false,
  "input": "https://www.amazon.com/dp/B0CWXNS552",
  "source": "woot-amazon-reviews",
  "scrapedAt": "2026-08-23T12:00:00.000Z"
}
```

#### Structured diagnostic rows

Diagnostics are written without a `review` billing event:

```json
{
  "error": "no_relevant_reviews_found",
  "errorDescription": "No written reviews matched the selected rating, keyword, and date filters.",
  "input": "https://www.amazon.com/dp/B0CWXNS552",
  "url": "https://www.amazon.com/dp/B0CWXNS552",
  "productAsin": "B0CWXNS552",
  "foundNoReviews": true,
  "partialResults": false,
  "reviewsSaved": 0,
  "failedRequests": 0,
  "scrapedAt": "2026-08-23T12:00:00.000Z"
}
```

When some requests exhaust their retries after reviews have already been saved,
the Actor adds a status row such as:

```json
{
  "error": "partial_results",
  "errorDescription": "Saved 42 reviews, but 1 review-feed request failed after all configured retries. Results may be incomplete.",
  "productAsin": "B0CWXNS552",
  "foundNoReviews": false,
  "partialResults": true,
  "reviewsSaved": 42,
  "failedRequests": 1
}
```

Possible codes are `invalid_url`, `no_relevant_reviews_found`,
`no_results_found`, `partial_results`, and `request_failed`.

### Coverage and current limitations

- **Amazon.com only.** A non-US Amazon URL is rejected instead of returning
  US reviews under the wrong marketplace label.
- **Written reviews only.** Amazon's total rating count includes star-only
  ratings; those are not review rows and are not available through this feed.
- The public feed caps each `(rating, sort)` pass at 100 reviews. Unlimited or
  keyword runs combine up to five rating groups and four sort orders. The
  number of unique rows depends on overlap and upstream availability.
- The source usually does not expose Amazon's real review ID. `reviewId` and
  `reviewUrl` therefore remain `null`; use the stable `reviewFingerprint` as
  the row key.
- Variant labels and variant filtering are not exposed by the source.
  `reviewsUseProductVariantFilter: true` is accepted for compatibility but
  logs a warning and does not narrow results.
- `scrapeProductDetails: true` adds only canonical `{ asin, url }` metadata.
  Use the separate Amazon Product Scraper for full product detail pages.
- Sort selects the primary retrieval order. Exhaustive scans may add alternate
  sort passes to improve coverage, so the final deduplicated dataset is not a
  guaranteed global sort order.

### Pricing

Pay per event:

- Actor start: **$0.001** for a run with at least one valid product.
- Review: **$0.003** per unique written review admitted to the dataset.

One thousand unique reviews cost **$3.001**. Invalid inputs, filtered rows,
duplicate rows, and structured diagnostic rows do not trigger the review event.
Apify run charge limits are honored immediately.

### Responsible use

The Actor processes publicly available review content. You are responsible for
complying with applicable law, Amazon and Woot terms, and your own contractual
obligations. Leave personal-information collection disabled unless you have a
lawful purpose, minimize retention, and do not use review data to harass or
profile individuals.

### Support

Open an issue from the Actor's **Issues** tab with the ASIN, sanitized input,
run ID, and expected behavior. Do not post private customer data or API tokens.

# Actor input Schema

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

Amazon.com product or product-review URLs. Direct 10-character ASIN strings are also accepted through the API. Other Amazon marketplaces are rejected rather than silently returning US review data.

## `maxReviews` (type: `integer`):

Maximum unique written reviews saved for each product. Set 0 to scan every available rating/sort pass. The source caps each pass at 100 reviews, so the exact unlimited total depends on overlap and product history.

## `includeGdprSensitive` (type: `boolean`):

Off by default. Enable only when you have a lawful reason to process reviewer display names. The public source does not expose profile IDs, links, or avatars.

## `sort` (type: `string`):

Chooses the primary source order. Broader scans may add alternate order passes to improve coverage, then deduplicate the result.

## `reviewsCutoffDate` (type: `string`):

Keep reviews on or after this UTC cutoff. Use YYYY-MM-DD, a full ISO timestamp, or relative time such as `2 weeks` or `3 months`. Reviews whose date cannot be verified are excluded when a cutoff is active.

## `filterByRatings` (type: `array`):

Select one or more rating groups. Overlapping groups such as All critical and 1 star are deduplicated before billing.

## `reviewsFilterByKeywords` (type: `array`):

Keep reviews whose title or body contains at least one keyword (case-insensitive). Each keyword is combined as OR; overlapping matches are deduplicated.

## `maxRequestRetries` (type: `integer`):

Retries transient HTTP, rate-limit, or malformed upstream responses.

## `maxConcurrency` (type: `integer`):

Concurrent review-feed requests. The Actor also limits the run to 120 requests per minute.

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

Optional escape hatch. The public Woot JSON transport normally works without a proxy, so leaving this unset is faster and cheaper.

## `reviewsUseProductVariantFilter` (type: `boolean`):

Accepted for compatibility. The public review feed does not expose variant selection, so enabling this currently logs a warning and returns all written reviews.

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

Accepted for compatibility. When enabled, the `product` field contains the canonical ASIN and Amazon.com URL; this focused Actor does not crawl the product detail page.

## `reviewsAlwaysSaveCategoryData` (type: `boolean`):

Accepted for compatibility. This Actor always writes a non-billable structured error row when a product has no matching written reviews.

## `deduplicateRedirectedAsins` (type: `boolean`):

Deduplicate multiple input URLs that identify the same ASIN. Disable only when you intentionally want one output budget per input URL.

## Actor input object example

```json
{
  "productUrls": [
    {
      "url": "https://www.amazon.com/dp/B0CWXNS552"
    }
  ],
  "maxReviews": 100,
  "includeGdprSensitive": false,
  "sort": "helpful",
  "filterByRatings": [
    "allStars"
  ],
  "maxRequestRetries": 3,
  "maxConcurrency": 5,
  "reviewsUseProductVariantFilter": false,
  "scrapeProductDetails": false,
  "reviewsAlwaysSaveCategoryData": false,
  "deduplicateRedirectedAsins": true
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset containing scraped review rows and any structured input errors.

# 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": [
        {
            "url": "https://www.amazon.com/dp/B0CWXNS552"
        }
    ],
    "maxReviews": 100,
    "filterByRatings": [
        "allStars"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("prodiger/amazon-reviews-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": [{ "url": "https://www.amazon.com/dp/B0CWXNS552" }],
    "maxReviews": 100,
    "filterByRatings": ["allStars"],
}

# Run the Actor and wait for it to finish
run = client.actor("prodiger/amazon-reviews-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": [
    {
      "url": "https://www.amazon.com/dp/B0CWXNS552"
    }
  ],
  "maxReviews": 100,
  "filterByRatings": [
    "allStars"
  ]
}' |
apify call prodiger/amazon-reviews-scraper --silent --output-dataset

```

## MCP server setup

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