# Trustpilot Scraper (`juanoox/trustpilot-scraper`) Actor

Scrape Trustpilot reviews with the field that decides whether a rating is earned: whether each review came in on its own or was solicited by the company.

- **URL**: https://apify.com/juanoox/trustpilot-scraper.md
- **Developed by:** [Juan ignacio Veltri](https://apify.com/juanoox) (community)
- **Categories:** E-commerce, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 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.

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

## Trustpilot Scraper

Scrapes Trustpilot reviews with the one field that decides whether a rating means
anything: **whether each review arrived on its own, or the company asked for it.**

### The field nobody exports

Trustpilot records the origin of every review. Companies can send invitations —
by email, by API, by a link on a receipt — and those reviews count toward the
public score exactly like the ones people write unprompted. It is not fraud and
Trustpilot does not hide it. But no export includes it, so every Trustpilot
dataset reads as if all reviews were spontaneous.

Two real companies, first page of reviews, on the same day:

| Company | TrustScore | Reviews the company asked for |
|---|---:|---:|
| Amazon | **1.6** | 0 of 20 |
| HelloFresh | **3.4** | 19 of 20 |
| Temu | **1.8** | 1 of 20 |
| Wish | **4.3** | 11 of 20 |

Wish outranks Temu by 2.5 stars. Half of Wish's reviews came in through a link
the company handed out; Temu's did not. That is the difference this Actor makes
visible, and it is one boolean away in the output:

```json
{ "origin": "invited", "originRaw": "BasicLink" }
```

Set `onlyOrganic` and the dataset holds only the reviews a company did not ask
for — the rating it earned rather than the one it collected.

`originRaw` carries Trustpilot's own label untouched, next to the normalized one.
Review platforms add new labels without notice; with both fields you can check
the classification against the source instead of trusting it.

### Input

Give it a domain. Trustpilot identifies companies by domain, so you rarely need
to open the site to find the right link:

```json
{ "startUrls": ["amazon.com", "hellofresh.com"] }
```

Full Trustpilot URLs and company websites work too — `https://www.trustpilot.com/review/www.amazon.com`
and `https://www.amazon.com/gp/help` both resolve to the same company.

Only the complaints, only the ones the company did not solicit, only this month:

```json
{
  "startUrls": ["temu.com"],
  "maxRating": 2,
  "onlyOrganic": true,
  "publishedAfter": "2026-08-01",
  "maxPagesPerBusiness": 50
}
```

| Parameter | Type | Default | What it does |
|---|---|---|---|
| `startUrls` | array | `["https://www.trustpilot.com/review/www.amazon.com"]` | Companies, as bare domains or URLs. |
| `maxPagesPerBusiness` | integer | `5` | 20 reviews per page, newest first. Large companies run past 4,000 pages. |
| `onlyOrganic` | boolean | `false` | Keep only reviews the company did not ask for. |
| `minRating` / `maxRating` | integer | — | 1 to 5. `maxRating: 2` reads only the complaints. |
| `onlyVerified` | boolean | `false` | Only reviews Trustpilot confirmed came from a real experience. |
| `onlyWithReply` | boolean | `false` | Only reviews the company answered in public. |
| `publishedAfter` | string | — | `YYYY-MM-DD`. Reviews come newest first, so this is the cheap way to fetch only what changed since your last run. |
| `languages` | array | — | Two-letter codes, e.g. `en`, `es`. |
| `keywords` | array | — | Keep reviews whose title or text matches, e.g. `refund`. |
| `maxItems` | integer | `200` | Hard cap on rows saved and charged. `0` means no cap. |
| `includeSeen` | boolean | `true` | Set to `false` to save only reviews never returned before. |

### Output

One row per review. Every row carries the company profile, so a single review is
readable without joining anything.

```json
{
  "id": "trustpilot:6a8c9114df2857f544f8fc47",
  "url": "https://www.trustpilot.com/review/www.amazon.com",
  "source": "trustpilot",
  "scrapedAt": "2026-08-24T21:10:41.547Z",
  "reviewId": "6a8c9114df2857f544f8fc47",
  "rating": 1,
  "title": "I don't know who is in charge of returns",
  "text": "It's been going on 20 days and I still have yet to get my return back...",
  "origin": "organic",
  "originRaw": "Organic",
  "isVerified": false,
  "publishedAt": "2026-08-24T20:44:36.000Z",
  "experiencedAt": "2026-08-04T00:00:00.000Z",
  "language": "en",
  "likes": 0,
  "reply": null,
  "author": { "name": "Brittany Ashby", "reviewsCount": 1, "country": "US", "isVerified": false },
  "business": {
    "id": "46ad346800006400050092d0",
    "name": "Amazon",
    "domain": "www.amazon.com",
    "score": 1.6,
    "reviewsCount": 48646,
    "categories": ["Book Store", "Clothing Store"],
    "country": "GB",
    "isClaimed": true,
    "collectsIncentivized": false,
    "alerts": []
  }
}
```

| Field | Notes |
|---|---|
| `origin` | `organic`, `invited`, `imported` or `unknown`. Never guesses: a label Trustpilot does not state stays `unknown` rather than being assumed spontaneous. |
| `originRaw` | Trustpilot's own label, unmodified. |
| `experiencedAt` | When the purchase or service happened, which Trustpilot asks for separately from the publish date. Twenty reviews published today about experiences from a year ago say nothing about how the company is doing now. |
| `author.reviewsCount` | How many reviews this person has written in total. A reviewer with exactly one carries less weight. |
| `business.score` | The TrustScore to one decimal, not the half-star value used for the star graphic. |
| `business.collectsIncentivized` | Trustpilot flags companies that offered something in exchange for reviews. When true, the average cannot be compared against a company that did not. |
| `business.alerts` | Warnings Trustpilot publishes about the company, raised when it detects review manipulation. The strongest signal on the profile. |
| `reply` | The company's public answer, with its date. |

The company's own AI summary of all its reviews is read but kept out of the
dataset: it is one per company, not one per review, and repeating it on every row
would multiply the export size for nothing.

### Cost

20 reviews per request, so this is the cheapest vertical we publish. Empty and
duplicate rows are never charged.

### Notes

Everything comes from the state Trustpilot ships to hydrate its own page —
already typed and normalized by Trustpilot — rather than from CSS selectors.
That is why a redesign does not break this parser: the markup around the review
cards changes often, the state that fills them does not.

Trustpilot filters clients by fingerprint, so the Actor runs behind Apify's
Unblocker. Verified against company pages, page 2 and category pages.

# Actor input Schema

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

One entry per company. A bare domain works — 'amazon.com' — and so does a full Trustpilot URL or the company's own website. Trustpilot identifies companies by domain, so you rarely need to open the site to find the right link.

## `maxPagesPerBusiness` (type: `integer`):

Each page holds 20 reviews, newest first. 5 pages is the last 100 reviews. Big companies run past 4,000 pages.

## `onlyOrganic` (type: `boolean`):

Trustpilot records whether each review arrived on its own or came from an invitation the company sent. Turning this on leaves only the unprompted ones — the rating a company earned rather than the one it collected. Reviews whose origin Trustpilot does not state are excluded too, since assuming they were spontaneous is exactly the mistake this filter exists to prevent.

## `minRating` (type: `integer`):

Keep reviews at or above this, 1 to 5. Leave empty for no filter.

## `maxRating` (type: `integer`):

Keep reviews at or below this. Set it to 2 to read only the complaints.

## `onlyVerified` (type: `boolean`):

Keep only reviews where Trustpilot confirmed the reviewer had a real experience with the company.

## `onlyWithReply` (type: `boolean`):

Useful for measuring how a company handles complaints in public.

## `publishedAfter` (type: `string`):

Ignore anything published before this date, as YYYY-MM-DD. Reviews come newest first, so this is the cheap way to fetch only what is new since your last run.

## `languages` (type: `array`):

Two-letter codes such as en or es. Empty keeps every language.

## `keywords` (type: `array`):

Keep only reviews whose title or text contains one of these, e.g. 'refund', 'delivery'.

## `maxItems` (type: `integer`):

Hard cap on how many reviews are saved and charged. 0 means no cap.

## `includeSeen` (type: `boolean`):

Off means the run only saves reviews it has never returned before, which is what you want when monitoring a company over time.

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

Parallel requests. Trustpilot filters aggressive clients, so higher is not faster.

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

How many times a blocked or failed request is retried before the company is given up on.

## `maxRequestsPerMinute` (type: `integer`):

Rate limit for the whole run.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.trustpilot.com/review/www.amazon.com"
  ],
  "maxPagesPerBusiness": 5,
  "onlyOrganic": false,
  "onlyVerified": false,
  "onlyWithReply": false,
  "publishedAfter": "",
  "maxItems": 200,
  "includeSeen": true,
  "maxConcurrency": 2,
  "maxRequestRetries": 3,
  "maxRequestsPerMinute": 30
}
```

# Actor output Schema

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

No description

## `runSummary` (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": [
        "https://www.trustpilot.com/review/www.amazon.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("juanoox/trustpilot-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": ["https://www.trustpilot.com/review/www.amazon.com"] }

# Run the Actor and wait for it to finish
run = client.actor("juanoox/trustpilot-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": [
    "https://www.trustpilot.com/review/www.amazon.com"
  ]
}' |
apify call juanoox/trustpilot-scraper --silent --output-dataset

```

## MCP server setup

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