# Amazon Review Scraper - Public Reviews & Star Histogram (`renzomacar/amazon-reviews`) Actor

Extracts the reviews Amazon shows publicly on a product page - typically 10-15 per ASIN - with rating, full text, verified flag, reviewer, date and helpful votes, plus the star histogram and aggregate rating. No login needed. Bulk review history requires an authenticated session (self-hosted).

- **URL**: https://apify.com/renzomacar/amazon-reviews.md
- **Developed by:** [Renzo Madueno](https://apify.com/renzomacar) (community)
- **Categories:** E-commerce, AI
- **Stats:** 13 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $6.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 Review Scraper — Ratings, Text, Verified, by ASIN

Extract real Amazon customer reviews for any product by **ASIN**. Returns one row per review with the star rating, title, full review text, verified-purchase flag, reviewer name and profile, date, helpful-vote count, product variant, and country.

Built on the same battle-tested HTTP + proxy + session-rotation stack as the [Amazon Product Scraper](https://apify.com/renzomacar/amazon-products).

***

### How many reviews you actually get (read this first)

**Amazon now requires sign-in for the full review pages.** Requesting
`https://www.amazon.com/product-reviews/<ASIN>` without a session returns a page with
**zero** reviews and a sign-in redirect, and the old
`/hz/reviews-render/ajax/reviews/get/` endpoint needs valid session cookies plus a
page-scoped CSRF token. The only reviews Amazon publishes to logged-out clients are the
**~13 embedded on the product page** — verified across many ASINs, it is consistently 13.

So, honestly:

| Mode | Reviews per ASIN | What else you get | Requirement |
|------|------------------|-------------------|-------------|
| `fast` (default) | **~13** | aggregate rating, total ratings, star histogram, "Customers say" AI summary | none |
| `deep` | up to ~100 per star filter | same | **your own** Amazon session cookie in `amazonCookies` |

`maxReviewsPerAsin` is capped at `100` and defaults to `13` for this reason. Setting it
higher in `fast` mode will not produce more reviews — no scraper can, the data is not
public — and the run logs an `ANON_CEILING` warning saying so instead of silently
returning fewer than you asked for.

**Billing:** this actor is pay-per-event and every result row is charged. If an ASIN is
delisted, blocked or gated so that **nothing public can be read**, the actor pushes **no
item at all** for it (logged as `NO_BILLABLE_OUTPUT`), so you are never charged for an
empty row.

***

### What you get (one item per review)

| Field | Description |
|-------|-------------|
| `asin` | The product ASIN the review belongs to |
| `reviewId` | Amazon's review id (e.g. `R2ABC123XYZ`) |
| `title` | Review headline |
| `rating` | Star rating as a number (1–5) |
| `body` | Full review text, plain text |
| `date` | ISO 8601 date when parseable |
| `dateRaw` | Original Amazon date string (e.g. `Reviewed in the United States on March 5, 2024`) |
| `verifiedPurchase` | `true` if the "Verified Purchase" badge is present |
| `reviewerName` | Display name of the reviewer |
| `reviewerProfileUrl` | Link to the reviewer's profile (when available) |
| `helpfulVotes` | Number of "found this helpful" votes (integer or `null`) |
| `foundHelpfulText` | Raw helpful-vote text |
| `variant` | Purchased variant, e.g. `Color: Black` (when shown) |
| `country` | Country the review was written in |
| `source`, `marketplace`, `productUrl`, `scrapedAt` | Provenance metadata |

#### Plus one ASIN-level summary row per product

In addition to the per-review rows, the actor emits **one summary item per ASIN** (`type: "asin_summary"`) carrying product-wide signal that Amazon shows anonymously on the product page:

| Field | Description |
|-------|-------------|
| `type` | Always `"asin_summary"` (review rows have no `type` field) |
| `asin` | The product ASIN |
| `aggregateRating` | Average star rating across **all** ratings (e.g. `4.2`) |
| `totalRatings` | Total number of ratings on the listing (e.g. `60175`) |
| `ratingHistogram` | Star distribution as percentages, e.g. `{ "fiveStar": 69, "fourStar": 12, "threeStar": 5, "twoStar": 3, "oneStar": 11 }` |
| `customersSay` | Amazon's AI review summary + most-mentioned aspects (see below), or `null` if absent |
| `reviewsCount` | How many individual review rows this run scraped for the ASIN |

`customersSay` shape:

```json
{
  "summary": "Customers find the iPhone in excellent condition, working like new... battery life and durability receive mixed reviews...",
  "aspects": [
    { "name": "Quality",      "sentiment": "positive", "mentions": "1.8K" },
    { "name": "Battery life",  "sentiment": "mixed",    "mentions": "2K" },
    { "name": "Durability",    "sentiment": "negative", "mentions": "591" }
  ]
}
```

`sentiment` is one of `positive` / `mixed` / `negative`. If a product has no "Customers say" widget, `customersSay` is `null` (never an error).

***

### Input

```json
{
  "asins": ["B00FLYWNYQ", "https://www.amazon.com/dp/0735211299"],
  "marketplace": "amazon.com",
  "maxReviewsPerAsin": 13,
  "sortBy": "recent",
  "filterByStar": "all",
  "reviewDepth": "fast"
}
```

| Field | Type | Default | Notes |
|-------|------|---------|-------|
| `asins` | array of strings | **required** | ASINs (`B00FLYWNYQ`) or full product URLs — the ASIN is auto-extracted. |
| `marketplace` | enum | `amazon.com` | `amazon.com`, `amazon.co.uk`, `amazon.de`, `amazon.fr`, `amazon.it`, `amazon.es`, `amazon.ca`, `amazon.com.au`, `amazon.co.jp`, `amazon.in`, `amazon.com.mx`, `amazon.com.br` |
| `maxReviewsPerAsin` | integer | `13` | Upper bound per ASIN. **Anonymously the real ceiling is ~13** (see *How many reviews you actually get* below); values above 13 only take effect with `reviewDepth: "deep"` + your own cookie. Max accepted: `100`. |
| `reviewDepth` | enum | `fast` | `fast` = anonymous route (~13 reviews/ASIN + aggregate rating + "Customers say"). `deep` = paginate past that ceiling using your own Amazon cookie. See **Review depth** below. |
| `sortBy` | enum | `recent` | `recent` or `helpful`. |
| `filterByStar` | enum | `all` | `all`, `five_star` … `one_star`, `positive`, `critical`. |
| `amazonCookies` | string (secret) | *empty* | **Optional.** Your own logged-in Amazon `Cookie` header. Unlocks `deep` pagination (up to ~100/ASIN per star filter). Empty = free anonymous route (~13/ASIN). See **BYO-cookie** section below. |

***

### Example output

```json
{
  "asin": "B00FLYWNYQ",
  "reviewId": "R2ABC123XYZ",
  "title": "Excellent battery life",
  "rating": 5,
  "body": "Works great, sound is clear and setup was easy. Highly recommend.",
  "date": "2024-03-05T00:00:00.000Z",
  "dateRaw": "Reviewed in the United States on March 5, 2024",
  "verifiedPurchase": true,
  "reviewerName": "Jane D.",
  "reviewerProfileUrl": "https://www.amazon.com/gp/profile/amzn1.account.ABC",
  "helpfulVotes": 12,
  "foundHelpfulText": "12 people found this helpful",
  "variant": "Color: Black",
  "country": "United States",
  "source": "product-page",
  "marketplace": "amazon.com",
  "productUrl": "https://www.amazon.com/dp/B00FLYWNYQ",
  "scrapedAt": "2026-06-07T00:00:00.000Z"
}
```

***

### Important: Amazon's anonymous-review ceiling (real limits, 2026)

Amazon limits how many reviews can be read **without logging in**. As of 2026 the dedicated `/product-reviews/` page is a **hard sign-in wall** for anonymous traffic, so the anonymous (`fast`) route returns the **recent, featured review "medley" embedded on the product page — typically about 10–20 reviews per ASIN**, fully populated (rating, title, body, verified, reviewer, date, helpful votes, variant), together with the **aggregate rating** and Amazon's **"Customers say"** AI summary.

This is honest and deterministic: the `fast` route does **not** return a product's entire review history. It returns the reviews Amazon surfaces publicly without a login. When Amazon gates further pages the actor **stops cleanly** and records a warning — it never fabricates data and never crashes.

To read **more** than the public medley, use `reviewDepth="deep"` with your own Amazon cookie (next section).

***

### Review depth — `fast` vs `deep`

- **`fast`** (default) — anonymous scraper. Returns the **~13 reviews Amazon embeds on the product page** plus the **aggregate rating** and **"Customers say"** AI summary. No login, no extra setup, fully deterministic.
- **`deep`** — pages **past the anonymous ceiling** (up to ~100 reviews per ASIN per star filter) by reusing **your own logged-in Amazon session cookie**. This is **self-hosted**: there are **no paid third-party services** involved. You supply your cookie in `amazonCookies`; the actor reads the page-scoped CSRF token and paginates Amazon's own `medley-filtered-reviews` endpoint, mapping every review into this actor's exact output schema (`source: "product-reviews-ajax"`).
  - **No cookie + `deep`** → the run records a `DEEP_NO_COOKIE` warning and **falls back to the `fast` route** for all ASINs. It never crashes.

***

### Unlock more reviews per ASIN — Bring Your Own Cookie (BYO-cookie)

To page **past the public medley** you must request as a logged-in Amazon session. Paste your own Amazon session cookies into the optional **`amazonCookies`** input (and set `reviewDepth="deep"`). The actor reads the page-scoped `reviewsCsrfToken` from `/dp/`, then pages `medley-filtered-reviews/get` across every star bucket (5★→1★), deduping by review id, up to `maxReviewsPerAsin`.

#### How to get your cookie (3 steps)

1. Log in to **https://www.amazon.com** in Chrome. **This is your own session** — use a **throwaway account**, never your primary login.
2. Open **DevTools** (F12) → **Application** tab → **Storage → Cookies → https://www.amazon.com**. Copy these cookie **name=value** pairs and join them with `; ` into one line:
   - `at-main`, `sess-at-main`, `session-id`, `session-id-time`, `session-token`, `ubid-main`, `x-main`  (optional: `lc-main`, `i18n-prefs`)
3. Paste the resulting string into the **`amazonCookies`** field and set `reviewDepth` to `deep`, e.g.:
   ```
   session-id=131-1234567-...; ubid-main=133-...; x-main=Atza|...; at-main=Atza|...; sess-at-main="..."; session-token=...; session-id-time=...
   ```
   You can also paste the **entire `Cookie:` request header** straight from DevTools → Network → any amazon.com request → Request Headers → Cookie; the actor parses it as-is.

#### Behavior & limits

- **Valid cookie** → paginated AJAX, up to ~100 reviews per ASIN per star filter (bounded by `maxReviewsPerAsin`). `route: cookie-ajax` in the summary.
- **Expired/rejected cookie** → the run records a **`COOKIE_EXPIRED`** warning and **falls back to the anonymous medley** for that ASIN (no crash). Re-export fresh cookies and re-run.
- Cookies are **session-scoped** (they expire — typically days to weeks). The `amazonCookies` field is stored as a **secret** input and is **your own session**, never shared.
- **IP soft-block vs. dead cookie are handled separately.** If Amazon serves a `404`/"Page Not Found" to a flagged residential IP (even with a perfectly valid cookie), the actor **rotates to a fresh residential IP up to 4×** before giving up, then falls back to the anonymous route — it does **not** mislabel the cookie as expired. A genuine sign-in wall is what triggers `COOKIE_EXPIRED`.

***

### Robustness

- **No reviews / invalid ASIN** → the run **succeeds** with a `NO_REVIEWS` warning (recorded under the `WARNINGS` key in the run's key-value store). No junk rows.
- **CAPTCHA / soft block** → the session is retired and the request is retried on a fresh proxy IP. If every ASIN is blocked, the run fails with an actionable `BLOCKED` error and a `FAILURES` record.
- **Partial results** → ASINs that succeed still return data even if others are gated or blocked.
- **Run summary** → a `SUMMARY` record (per-ASIN extracted count, pages, blocked/gated flags) is written to the key-value store on every run.

***

### Tips

- Start with `sortBy: "recent"` to get the freshest signal, or `helpful` for the most-voted reviews.
- Use `filterByStar: "critical"` to pull only 1–3★ reviews for complaint mining, or `positive` for testimonials.
- Lower `maxConcurrency` (1–2) if you see blocks on large batches.

# Actor input Schema

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

Amazon ASINs (e.g. 'B00FLYWNYQ') or full product URLs. The ASIN is auto-extracted from URLs. Delisted/removed ASINs return no reviews (nothing is charged for them).

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

Which Amazon domain to scrape reviews from.

## `maxReviewsPerAsin` (type: `integer`):

Upper bound of reviews per ASIN. REAL LIMIT: anonymously (reviewDepth="fast", the default) Amazon publishes only the ~13 reviews embedded on the product page - the full /product-reviews/ pages now require sign-in. Setting this above 13 does NOT return more in fast mode. Values above 13 are only reachable with reviewDepth="deep" plus your own Amazon session cookie in "amazonCookies".

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

Order reviews by most recent or most helpful. With reviewDepth="fast" the sort is applied locally over the ~13-review product-page medley; use reviewDepth="deep" (cookie) to sort across all reviews.

## `filterByStar` (type: `string`):

Only return reviews matching this star filter. NOTE on depth: with reviewDepth="fast" the filter is applied locally over the embedded /dp/ medley (~13 reviews), so it narrows that small universe (the run logs a FILTER\_APPLIED\_FAST warning showing how many matched). To filter across the product's FULL review set, use reviewDepth="deep". 'Positive' = 4-5 stars, 'Critical' = 1-2 stars.

## `reviewDepth` (type: `string`):

fast = anonymous scraper, no login: returns the ~13 reviews Amazon embeds on the product page + aggregate rating + rating histogram + "Customers say" AI summary. This is ALL that is publicly available - Amazon gates the full /product-reviews/ pages behind sign-in. deep = paginate past that ceiling (up to ~100/ASIN per star filter) using YOUR OWN Amazon session cookie supplied in "amazonCookies". If "deep" is selected without a cookie, the run logs a warning and falls back to fast.

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

Number of review pages to process in parallel. Lower is safer against bot detection.

## `amazonCookies` (type: `string`):

OPTIONAL (enables reviewDepth="deep"). Paste YOUR OWN logged-in Amazon Cookie header to page PAST the ~13-review anonymous ceiling (up to ~100/ASIN per star filter). Get it from DevTools -> Application -> Cookies -> https://www.amazon.com -> copy these into a single 'name=value; name=value' string: at-main, sess-at-main, session-id, session-id-time, session-token, ubid-main, x-main (lc-main and i18n-prefs optional). Leave EMPTY to use the free anonymous route (~13 reviews/ASIN). Cookies expire - if Amazon rejects them the run records a COOKIE\_EXPIRED warning and falls back to the anonymous medley. This is YOUR session: use a throwaway Amazon account, never your primary login.

## Actor input object example

```json
{
  "asins": [
    "B00FLYWNYQ",
    "https://www.amazon.com/dp/0735211299"
  ],
  "marketplace": "amazon.com",
  "maxReviewsPerAsin": 13,
  "sortBy": "recent",
  "filterByStar": "all",
  "reviewDepth": "fast",
  "maxConcurrency": 3
}
```

# Actor output Schema

## `results` (type: `string`):

All scraped items as JSON.

# 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 = {
    "asins": [
        "B00FLYWNYQ"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("renzomacar/amazon-reviews").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 = { "asins": ["B00FLYWNYQ"] }

# Run the Actor and wait for it to finish
run = client.actor("renzomacar/amazon-reviews").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 '{
  "asins": [
    "B00FLYWNYQ"
  ]
}' |
apify call renzomacar/amazon-reviews --silent --output-dataset

```

## MCP server setup

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

```

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/DeHkBqExl3V2XcvBl/builds/KdM5qOFa7m5Ma5gLF/openapi.json
