# Trustpilot Search Scraper — Find Companies by Name (`thenetaji/trustpilot-search-scraper`) Actor

Find companies on Trustpilot by name, brand or keyword when the profile address is unknown. Each match comes back with its TrustScore, review count, location and the company's own website, email and phone, ready for a prospect list or a competitor sweep.

- **URL**: https://apify.com/thenetaji/trustpilot-search-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 $1.28 / 1,000 company founds

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

The Actor looks companies up on Trustpilot by name, brand or plain keyword and returns each match as
a row with its TrustScore, star rating, review count, location, claim status, and the company's own
website, email and phone. It is the Actor to reach for when a company is known by its name and not by
its Trustpilot address.

Two things make it worth a run. Company keys on Trustpilot are load-bearing and awkward to guess, so
resolving a name to `domain` here is more reliable than constructing one, and `domain` then feeds
[Trustpilot Reviews Scraper](https://apify.com/thenetaji/trustpilot-reviews-scraper) and
[Trustpilot Company Scraper](https://apify.com/thenetaji/trustpilot-company-scraper) directly. The
second is the contact block: a search row carries the company's own website, email and phone without
a second request, which no other listing on the site does. A keyword such as `insurance` therefore
turns into a scored, contactable list of companies in a single run.

### Accepted input

`query` is required and accepts a company name, a brand, or a plain word, between 1 and 200
characters. `maxItems` caps how many companies are saved and defaults to 100; a value of `0` removes
the cap. `enrichCompanyDetails` defaults to `false` and is described below.

```json
{
  "query": "insurance",
  "maxItems": 20,
  "enrichCompanyDetails": false
}
```

### Response fields

```json
{
  "domain": "rac.co.uk/insurance",
  "business_unit_id": "5060f52a00006400051bf99f",
  "display_name": "RAC Car Insurance",
  "profile_url": "https://www.trustpilot.com/review/rac.co.uk/insurance",
  "trust_score": 4.4,
  "stars": 4.5,
  "rating_scale_max": 5,
  "review_count": 18579,
  "is_claimed": true,
  "logo_url": "https://s3-eu-west-1.amazonaws.com/tpd/x/198x149.png",
  "categories": [{ "id": "insurance_agency", "name": null, "is_primary": true }],
  "city": "London",
  "country": "GB",
  "contact_website": "https://www.sterling-insurance.co.uk",
  "contact_email": null,
  "contact_phone": null,
  "position": 1
}
```

| Field | What it says |
| --- | --- |
| `trust_score` | Trustpilot's underlying score out of five, to one decimal. Sort and compare on this one. |
| `stars` | The same assessment rounded to the half star, which is what Trustpilot renders; a `trust_score` of 4.4 displays as 4.5. |
| `rating_scale_max` | The top of the scale, always 5 here, stated per row so a rating is never compared against a ten-point scale by accident. |
| `review_count` | How many reviews the score is computed over. |
| `is_claimed` | Whether the company has taken control of its Trustpilot profile. |
| `contact_website`, `contact_email`, `contact_phone` | The company's own details. `contact_website` leaves Trustpilot; `profile_url` does not. |
| `city`, `country` | Where the company is, as the search listing states it. |
| `categories` | The categories Trustpilot files the company under. Each `id` is a slug [Trustpilot Category Scraper](https://apify.com/thenetaji/trustpilot-category-scraper) accepts. |
| `domain`, `business_unit_id`, `display_name`, `profile_url`, `logo_url` | Identity, and the key the sibling Actors take. |
| `position` | Where the row appeared in Trustpilot's ranking, counting from 1 across the run. |

The example key is not decorative. `rac.co.uk/insurance` genuinely appears in the first page of
results for `insurance`, and it is a different company from `rac.co.uk`: 18,579 reviews against
211,451. `domain` should be passed onward byte for byte.

### Adding reply behaviour and full company details

`enrichCompanyDetails` is off by default. Turning it on opens each company's own Trustpilot profile
and adds the numbers that a listing row does not carry: `reply_percentage`,
`average_days_to_reply`, `negative_reviews_with_replies_count`, `last_reply_to_negative_review`,
`claimed_date`, `previously_claimed`, `has_subscription`, `is_using_paid_features`, `is_closed`,
`is_temporarily_closed`, `is_collecting_reviews`, `locations_count`, `contact_country`,
`review_count_last_12_months`, `total_reviews`, `total_filtered_reviews`, `review_pages`,
`rating_distribution`, `review_languages`, `has_multiple_languages`, `has_consumer_alerts` and
`consumer_alerts`.

That costs one extra request per company and turns a twenty-company run from two requests into
twenty-two, so it should be left off where the score and the contact details are sufficient. It is
billed per company enriched and only after the lookup succeeds. A company for which Trustpilot serves
no profile page keeps its search row unchanged and is not billed, and contact fields the search row
already carried are kept where the profile states none.

### Questions

**Why did a run save fewer companies than Trustpilot says match the query?**
Two reasons combine. Trustpilot's stated total counts appearances rather than distinct companies:
the measured example reported 9,779 matches across 978 pages. And search pages overlap, because
relevance ranking is not a stable sequence; on a measured query, page 2 repeated two of its ten
companies from page 1. Repeats are dropped on `business_unit_id`, which stays stable when a company
changes its domain, and a dropped repeat does not consume the run's cap. The saved rows are distinct
companies; the stated total is not.

**Why does `position` skip numbers?**
`position` records where a row appeared in Trustpilot's ranking, counting every result returned
including the ones that turned out to be repeats of an earlier page. A gap in `position` is a
duplicate that was dropped.

**Can results be restricted to one country?**
Not on this Actor. Only the query and the page are wired, because Trustpilot answers an unrecognised
filter value with a normal response and its default ordering, which would make an unverified filter a
silent no-op rather than an error. `country` is available on
[Trustpilot Category Scraper](https://apify.com/thenetaji/trustpilot-category-scraper), where it has
been measured.

**Why are `contact_email` and `contact_phone` so often `null`?**
Because the company published no email or phone on Trustpilot. `contact_website` is the field that is
usually present; the other two are filled only where the company states them, and nothing is inferred
from the domain to fill the gap. `categories` is null in the same honest way: a search row states each
category's `id` and leaves `name` as `null`, because Trustpilot publishes only the id and the primary
flag on this listing. The `id` is the part the Category Actor needs.

**There is no street address on a search row. Where is it?**
On category rows. A search row states a city and a country; a category row states a street address and
a city and no country, so the two listings carry different halves of a location. Running
[Trustpilot Category Scraper](https://apify.com/thenetaji/trustpilot-category-scraper) for a slug from
the `categories` column is how to get the address for the same companies.

**A query returned no rows. Is that a failure?**
No. A query that matches nothing produces a normal, empty result set and the run completes. A failure
would have ended the run with an error.

**A broad keyword returns companies I do not want. What is the better tool?**
A category directory. The run log prints the category slugs Trustpilot suggests for the query on its
first page, and those slugs go straight into
[Trustpilot Category Scraper](https://apify.com/thenetaji/trustpilot-category-scraper), which returns
a whole market in Trustpilot's own ranked order rather than the matches for a phrase.

**Search returns ten rows a page while the other Actors return twenty. Does that change anything?**
Only the number of requests behind a given row count, which is why a company found by search is
priced above a company read from a category directory. Nothing about the pagination has to be
configured; `maxItems` counts saved companies either way.

### Related Actors

[Trustpilot Category Scraper](https://apify.com/thenetaji/trustpilot-category-scraper) exports a
whole ranked directory rather than the matches for a phrase.
[Trustpilot Company List Scraper](https://apify.com/thenetaji/trustpilot-company-list-scraper)
enumerates every company Trustpilot publishes, for cases where a search phrase is the wrong starting
point.

# Actor input Schema

## `query` (type: `string`):

A company name, a brand, or a plain word to search for.

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

Maximum companies to save. Set 0 for no limit. Results come 10 to a page and repeats between pages are dropped, so this counts distinct companies.

## `enrichCompanyDetails` (type: `boolean`):

Open each company's own Trustpilot profile and add what a listing row does not carry: the reply rate, the average days to reply, how many negative reviews were answered, the date the profile was claimed, the contact email and phone, the full star distribution, and both review totals. One extra request per company — slower, and billed per company added.

## Actor input object example

```json
{
  "query": "insurance",
  "maxItems": 20,
  "enrichCompanyDetails": false
}
```

# 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 = {
    "query": "insurance",
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("thenetaji/trustpilot-search-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 = {
    "query": "insurance",
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("thenetaji/trustpilot-search-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 '{
  "query": "insurance",
  "maxItems": 20
}' |
apify call thenetaji/trustpilot-search-scraper --silent --output-dataset

```

## MCP server setup

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