# Trustpilot Reviews Scraper (`zyra/trustpilot-reviews-scraper`) Actor

Scrape Trustpilot reviews for any company: rating, title, text, dates, reviewer and company replies, plus the company profile and its star breakdown. Filter by stars, date, language, keyword or topic.

- **URL**: https://apify.com/zyra/trustpilot-reviews-scraper.md
- **Developed by:** [Zyra](https://apify.com/zyra) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

$2.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

## Trustpilot Reviews Scraper

Get every review for a company on Trustpilot — rating, title, text, dates,
reviewer, company replies — plus the company's own profile and its star
breakdown, as clean structured JSON.

One company per run. Filter by star rating, date, language, keyword or topic
before anything is collected, so you pay for the reviews you actually want.

### What you get

**One dataset item per review**, with the company it belongs to attached to
each one. That means a CSV export is a spreadsheet of reviews, one per row,
with no unpacking to do.

```jsonc
{
  "id": "6a9fd4ce9b47cd282c8b408c",
  "url": "https://www.trustpilot.com/reviews/6a9fd4ce...",
  "title": "Geweldige acteurs/zangers",
  "content": "Geweldige acteurs/zangers. Een prachtig verhaal...",
  "rating": 5,
  "verified": false,
  "dates": {
    "written":    "2026-09-08T11:26:38.000Z",
    "experience": "2026-09-07T00:00:00.000Z",
    "posted_raw": null
  },
  "engagement": { "useful_count": 0, "reply_count": 0 },
  "replies":  [ { "content": "We're sorry to hear this...",
                  "date": "2026-09-09T10:00:00.000Z", "author": null } ],
  "reviewer": { "name": "M. K.", "country": "NL", "reviews_posted_overall": 2 },

  "company": {
    "id": "59935d1d0000ff0005a8efd0",
    "name": "Headout",
    "url": "https://www.trustpilot.com/review/headout.com",
    "website": "https://www.headout.com",
    "logo": "https://...",
    "about": "Headout is home to the world's best real-life experiences...",
    "verified": false,
    "contact":    { "email": "support@headout.com", "phone": "+1 347 897 0100" },
    "location":   { "address": "...", "country": "US" },
    "categories": { "primary": "travel_agency", "other": [],
                    "activity": [...], "breadcrumbs": [...] },
    "rating": {
      "score": 4.4,
      "label": "Excellent",
      "total_reviews": 62859,
      "distribution": [ { "star": 5, "count": 46343, "percentage": 74.0 }, ... ]
    }
  }
}
```

#### Field reference

**Review** — the item itself

| Field | Type | Notes |
| --- | --- | --- |
| `id` · `url` | string | `url` links straight to the review on Trustpilot |
| `rating` | integer | 1–5 |
| `title` · `content` | string | `content` may be `null` — a rating with no text |
| `verified` | boolean | Verified purchase/experience |
| `dates.written` | ISO 8601 | When the review was posted. **Use this one** |
| `dates.experience` | ISO 8601 | When the reviewer used the service |
| `dates.posted_raw` | string | Trustpilot's own wording, often a bucket like `Last 6 months`. `null` whenever Trustpilot showed an exact date |
| `engagement.useful_count` | integer | "Useful" votes from other readers |
| `engagement.reply_count` | integer | How many company replies |
| `replies[]` | object\[] | `content`, `date`, `author` |
| `reviewer.name` | string | Display name |
| `reviewer.country` | string | ISO 3166-1 alpha-2 |
| `reviewer.reviews_posted_overall` | integer | Their lifetime Trustpilot review count |

**Company** — under `company`, identical on every row of a run

| Field | Type | Notes |
| --- | --- | --- |
| `company.id` · `name` · `url` | string | `url` is the Trustpilot page, with your filters on it |
| `company.website` | string | The company's own site |
| `company.logo` · `about` | string | May be `null`; `about` may contain HTML |
| `company.verified` | boolean | Whether Trustpilot has verified the business |
| `company.contact.email` · `phone` | string | May be `null` |
| `company.location.address` · `country` | string | Country is ISO 3166-1 alpha-2 |
| `company.categories.primary` | string | Main Trustpilot category |
| `company.categories.other` · `activity` · `breadcrumbs` | string\[] | |
| `company.rating.score` | number | TrustScore, 1–5 |
| `company.rating.label` | string | `Excellent`, `Great`, `Average`… |
| `company.rating.total_reviews` | integer | Every review the company has, not just those collected |
| `company.rating.distribution[]` | object\[] | `star`, `count`, `percentage`, always ordered 5 → 1 |

Timestamps are ISO 8601 UTC with milliseconds (`2026-09-08T11:26:38.000Z`).
Any field can be `null` when Trustpilot does not show it.

### Input

The only required field is the company.

```json
{
  "companyDomain": "headout.com",
  "date": "last3months",
  "stars": ["1", "2"],
  "limit": 100
}
```

| Field | Type | Default | What it does |
| --- | --- | --- | --- |
| `companyDomain` | string | — | **Required.** `headout.com`, or a Trustpilot URL like `https://www.trustpilot.com/review/headout.com` (any regional domain works) |
| `limit` | integer | `100` | How many reviews to keep |
| `date` | select | all time | `last30days` · `last3months` · `last6months` · `last12months` |
| `stars` | multi-select | all | Any of `1`–`5`, combined as OR |
| `languages` | string | all | `all`, or an ISO 639-1 code such as `en` |
| `search` | string | — | Only reviews containing this text |
| `topics` | string\[] | — | Trustpilot topic slugs; the list differs per company |
| `verified` | any/yes/no | `any` | Verified reviews only, or unverified only |
| `replies` | any/yes/no | `any` | Only reviews the company has replied to, or only those without a reply |
| `sort` | select | `relevance` | `relevance` or `recency` |
| `datePosted` | select | — | A second date filter — see the note below |
| `page` | integer | `1` | Start from a later page of the review list |

### Pricing

Pay per review actually delivered — you are never charged for a run that
returns nothing. The current rates are on this actor's **Pricing** section
above; there are two, and a paid Apify plan pays the lower one.

A free Apify plan gets **5 runs** of this actor in total, and each of them
keeps at most **10 reviews**. Upgrading your Apify plan lifts both limits and
moves you to the lower rate.

A run refused for being past the free limit finishes with an empty dataset and
a status message saying so. It is not charged, and it does not count as a
failure.

Billing is issued in increments of 100 reviews, so the charge always matches
what was delivered.

### Things worth knowing

**`limit` caps what you keep, filters cap what gets collected.** Both reduce
cost, but the filters are the ones that make a run finish sooner. Leaving every
filter empty on a company with 60,000 reviews means collecting all of them.

**`limit` is a ceiling, not a promise.** A narrow filter — or Trustpilot simply
having fewer matching reviews — returns less. Asking for 250 might return 206,
and you are billed for the 206.

**`verified` and `replies` have three states, not two.** `any` applies no
filter at all. `yes` and `no` are two *different* filters — `no` gives you
unverified reviews only, which is not the same as "don't filter".

**`date` and `datePosted` are separate filters.** `date` is Trustpilot's own
and the one to use. Setting both applies both, and you get only the reviews
matching each — usually fewer than you expected.

**One row per review, and the company repeats on every row.** That is what
makes a CSV export usable directly. The dataset's **Company** view shows the
profile on its own if that is what you came for.

**A company with no matching reviews is a success, not an error.** You get an
empty dataset and a run that says so. A domain that has no Trustpilot page at
all fails the run and tells you so — the two are never confused.

### Examples

**Recent complaints, for support triage**

```json
{ "companyDomain": "headout.com", "stars": ["1", "2"],
  "date": "last30days", "sort": "recency", "limit": 200 }
```

**English reviews mentioning refunds**

```json
{ "companyDomain": "headout.com", "search": "refund",
  "languages": "en", "limit": 100 }
```

**Reviews the company has already answered**

```json
{ "companyDomain": "headout.com", "replies": "yes", "limit": 50 }
```

### Support

Runs are asynchronous and typically finish in under a minute; a large
unfiltered collection takes longer. Every run writes an `OUTPUT` record to the
key-value store with what was requested, what arrived, and what was charged.

If a run fails, its status message says why in plain language — a malformed
company domain, a company with no Trustpilot page, or a temporary problem
worth retrying.

# Actor input Schema

## `companyDomain` (type: `string`):

The company's own domain, such as 'headout.com'. Its Trustpilot reviews URL works too, on any regional domain (www., ca., ie.…), and filters already on that URL are kept unless a field below overrides them.

## `date` (type: `string`):

Recency filter, applied on the Trustpilot page itself. This is the confirmed one — prefer it over 'Date posted'.

## `stars` (type: `array`):

Any number of ratings; they combine as OR. Leave empty for all.

## `languages` (type: `string`):

'all', or an ISO 639-1 code such as 'en'. Only 'all' is confirmed to behave as documented.

## `search` (type: `string`):

Only reviews containing this text, searched within the company's reviews.

## `topics` (type: `array`):

Trustpilot topic slugs, one per row. The vocabulary is per company — read the slugs off the company's own review page.

## `verified` (type: `string`):

'Any' applies no filter at all. 'Verified only' and 'Unverified only' are two different filters, not a checkbox — which is why there is no unticked state that quietly means one of them.

## `replies` (type: `string`):

Whether to restrict to reviews the company has replied to.

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

Trustpilot's default is relevance. 'Most recent' is the only alternative it offers.

## `datePosted` (type: `string`):

A second recency filter, applied by the collection rather than the page. Setting both this and 'Reviews from the last…' applies both, and the result is their intersection.

## `page` (type: `integer`):

Start from this page of the company's review list instead of the first.

## `limit` (type: `integer`):

How many reviews to keep. This truncates the result — it does not narrow the collection, so a small limit costs the same as a large one. Use the filters above to actually collect less.

## Actor input object example

```json
{
  "companyDomain": "headout.com",
  "verified": "any",
  "replies": "any",
  "sort": "relevance",
  "limit": 100
}
```

# Actor output Schema

## `reviews` (type: `string`):

Every review collected, one item per review with its company attached.

## `runSummary` (type: `string`):

What was requested, what arrived, what was charged, and anything the run had to drop.

# 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 = {
    "companyDomain": "headout.com"
};

// Run the Actor and wait for it to finish
const run = await client.actor("zyra/trustpilot-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 = { "companyDomain": "headout.com" }

# Run the Actor and wait for it to finish
run = client.actor("zyra/trustpilot-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 '{
  "companyDomain": "headout.com"
}' |
apify call zyra/trustpilot-reviews-scraper --silent --output-dataset

```

## MCP server setup

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