# Trustpilot Company Scraper — Reply Rate & Contacts (`thenetaji/trustpilot-company-scraper`) Actor

Benchmark how a company handles its Trustpilot reviews. Every row states what share it answers, how long it takes, how many negative reviews got a reply and when the last one was. Trustpilot's own page shows none of those numbers. Contact details and the star split come with it.

- **URL**: https://apify.com/thenetaji/trustpilot-company-scraper.md
- **Developed by:** [The Netaji](https://apify.com/thenetaji) (community)
- **Categories:** Business, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.25 / 1,000 company profiles

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

## Trustpilot Company Scraper

The Actor answers one question about any company on Trustpilot: how seriously does it take its
reviews? Give it a list of companies and each comes back as a single row stating what share of its
reviews it answers, how many days it takes on average, how many negative reviews it has replied to,
and the date of the last of those. The company's contact details, categories, claim status, review
totals and full star breakdown come in the same row.

Those first four numbers are the point. Trustpilot renders none of them on the company's public
page, so the ordinary way to find out whether a competitor answers complaints is to read its reviews
and count by hand. This returns the figure directly, for as many companies as are listed, one row
each. Support teams use it to benchmark their own response behaviour against the rest of a market;
agencies use it to show a prospect where it stands.

### Accepted input

`domain` is required and accepts one or more Trustpilot company keys, one per entry. A pasted
Trustpilot company URL is accepted and reduced to the key. `maxItems` caps how many companies are
saved and defaults to 100; a value of `0` removes the cap.

```json
{
  "domain": ["www.amazon.com", "rac.co.uk/insurance", "www.rac.co.uk"],
  "maxItems": 100
}
```

The second and third keys in that example are deliberate, and the FAQ below explains why they are
two different companies rather than a typo.

Keys rarely have to be typed by hand.
[Trustpilot Search Scraper](https://apify.com/thenetaji/trustpilot-search-scraper),
[Trustpilot Category Scraper](https://apify.com/thenetaji/trustpilot-category-scraper) and
[Trustpilot Company List Scraper](https://apify.com/thenetaji/trustpilot-company-list-scraper) all
return the key in a `domain` column, and that column can be pasted straight in here.

### Response fields

```json
{
  "domain": "www.amazon.com",
  "business_unit_id": "47b8e2f0000064000502b1c3",
  "display_name": "Amazon",
  "profile_url": "https://www.trustpilot.com/review/www.amazon.com",
  "country": "GB",
  "categories": [{ "id": "shoe_store", "name": "Shoe Store", "is_primary": false }],
  "review_count": 48410,
  "review_count_last_12_months": 8925,
  "total_reviews": 45550,
  "total_filtered_reviews": 29953,
  "review_pages": 1498,
  "rating_distribution": [{ "rating": 1, "count": 32298 }],
  "review_languages": [{ "iso_code": "all", "review_count": 45550 }],
  "has_multiple_languages": true,
  "contact_email": null,
  "contact_phone": null,
  "contact_country": "GB",
  "is_claimed": true,
  "claimed_date": "2015-02-18T19:08:43.000Z",
  "previously_claimed": false,
  "has_subscription": true,
  "is_using_paid_features": true,
  "is_closed": false,
  "is_temporarily_closed": false,
  "is_collecting_reviews": true,
  "locations_count": 1,
  "has_consumer_alerts": false,
  "consumer_alerts": [],
  "reply_percentage": 12,
  "average_days_to_reply": 3,
  "negative_reviews_with_replies_count": 41,
  "last_reply_to_negative_review": null
}
```

| Field | What it says |
| --- | --- |
| `reply_percentage` | Share of its reviews the company answers, as a percentage. |
| `average_days_to_reply` | How long an answer takes, in days, on average. |
| `negative_reviews_with_replies_count` | How many negative reviews received an answer. |
| `last_reply_to_negative_review` | When the company last answered a negative review. |
| `is_claimed`, `claimed_date`, `previously_claimed` | Whether the company controls its profile, and since when. |
| `has_subscription`, `is_using_paid_features` | Whether the company pays Trustpilot. |
| `review_count`, `total_reviews`, `total_filtered_reviews` | Three separate totals; see the FAQ. |
| `review_count_last_12_months` | Reviews in the last year, which shows whether a rating is current. |
| `review_pages`, `rating_distribution`, `review_languages`, `has_multiple_languages` | Volume, star split and language split. |
| `contact_email`, `contact_phone`, `contact_country` | The contact details the company publishes on Trustpilot. |
| `is_closed`, `is_temporarily_closed`, `is_collecting_reviews`, `locations_count` | Trading status and how many locations Trustpilot holds. |
| `has_consumer_alerts`, `consumer_alerts` | Trustpilot's own warning banner, where it has posted one. |
| `domain`, `business_unit_id`, `display_name`, `profile_url`, `categories`, `country` | Identity, and the keys that feed the sibling Actors. |

Fields absent from the upstream response are returned as `null` rather than omitted, and
`categories`, `rating_distribution`, `review_languages` and `consumer_alerts` are returned as empty
lists rather than `null` where the company has none.

### Questions

**Why do three review counts disagree on the same company?**
Because Trustpilot publishes three, and all three are real. On one measured company they were 48,410,
45,550 and 29,953. `review_count` is the headline figure on the profile; `total_reviews` is every
review the company holds; `total_filtered_reviews` is the subset matching Trustpilot's default
language filter, and it is the only one that review pagination walks. All three are published
separately rather than reconciled, because reconciling them would mean inventing a number Trustpilot
does not state. `review_languages` breaks the gap between the second and third down by language.

**A reply percentage of 0 means the company ignores its customers, correct?**
Not necessarily. An unclaimed profile cannot reply at all, so read `is_claimed` alongside it. Reading
`has_subscription` is worth the trouble too: `is_claimed` means the company has taken control of the
profile, which is free, while `has_subscription` means it pays Trustpilot. Invitation-driven review
collection is a paid feature, and it moves both review volume and average rating.

**Why is `negative_reviews_with_replies_count` set while `last_reply_to_negative_review` is empty?**
That combination is Trustpilot stating that it does not hold a date, not a contradiction between two
fields. Both values are taken from the company record as published and neither is computed here.

**Where is the TrustScore?**
Not on this record. The company page states review counts and the full star distribution but not the
score itself, which appears on directory rows instead;
[Trustpilot Search Scraper](https://apify.com/thenetaji/trustpilot-search-scraper) and
[Trustpilot Category Scraper](https://apify.com/thenetaji/trustpilot-category-scraper) both return
`trust_score`. An average derived from `rating_distribution` is a different number from Trustpilot's
TrustScore, so none is computed and published under that name.

**A key was trimmed at the first slash and the row looks wrong. What happened?**
It returned a different company. `rac.co.uk/insurance` is RAC Car Insurance with 18,579 reviews;
`www.rac.co.uk` is RAC Breakdown Cover with 211,451. Both are valid keys, both return a real record,
and neither fails, so a truncated key produces plausible data about the wrong business. Keys are
passed through unchanged for that reason, including any path and including non-ASCII spellings such
as `kørkort.dk`, which Trustpilot files un-punycoded. The `www.` prefix is part of the spelling, not
decoration.

**What happens to a company that has closed since the list was built?**
A key for which Trustpilot serves no company page produces no row. The key is named in the run log
and the run continues with the next one, so a stale list of five hundred domains still returns the
records for those that exist. Nothing is billed for a key that returned no record.

**How many requests does a run of 500 companies make?**
Five hundred, one per company. There is no batch form of this lookup, which is why a company record
costs considerably more per row than a review does; a review page returns twenty rows for the same
single request. `maxItems` therefore bounds the requests a run makes as well as the rows it saves.

**Can these numbers be attached to search or category results without listing every key by hand?**
Yes. Both of those Actors carry an enrichment toggle that attaches this same record to each row at
one extra request per company, billed only after the request returns a company.

### Related Actors

[Trustpilot Reviews Scraper](https://apify.com/thenetaji/trustpilot-reviews-scraper) returns the
reviews themselves for the same keys.
[Trustpilot Company List Scraper](https://apify.com/thenetaji/trustpilot-company-list-scraper)
produces keys in bulk for feeding into this Actor.

# Actor input Schema

## `domain` (type: `array`):

Trustpilot company keys, one per line — for example www.amazon.com. A pasted Trustpilot company URL works too. Keys are case-insensitive and the `www.` is part of the key, not decoration. Some keys carry a path (`rac.co.uk/insurance`), which is a different company from `rac.co.uk` — pass keys through exactly as you got them. Every row returned by the Search, Category and Company List Actors carries the key in its `domain` field.

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

Maximum companies to save. Set 0 for no limit. One row and one request per company, so this is also the number of requests the run makes.

## Actor input object example

```json
{
  "domain": [
    "www.amazon.com"
  ],
  "maxItems": 5
}
```

# Actor output Schema

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

All records scraped by this run

# 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 = {
    "domain": [
        "www.amazon.com"
    ],
    "maxItems": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("thenetaji/trustpilot-company-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 = {
    "domain": ["www.amazon.com"],
    "maxItems": 5,
}

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

```

## MCP server setup

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