Trustpilot Reviews Scraper avatar

Trustpilot Reviews Scraper

Pricing

Pay per event

Go to Apify Store
Trustpilot Reviews Scraper

Trustpilot Reviews Scraper

Public Trustpilot reviews of any company by domain: rating, title, text, language, date, useful votes and the company reply. Reviewer data hashed, emails and phones redacted.

Pricing

Pay per event

Rating

0.0

(0)

Developer

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

4 days ago

Last modified

Categories

Features

Limited permissions

Share

Trustpilot Reviews Scraper extracts the public reviews of any company on Trustpilot by domain: star rating, title, text, language, publication date, useful votes and the company reply when there is one. Give it domains such as booking.com or Trustpilot profile URLs and get clean, deduplicated JSON, CSV or Excel. It is a Trustpilot reviews API alternative for reputation monitoring, customer-experience analytics, competitor tracking and sentiment analysis, and you need no Trustpilot account.

Reviewer names are included and can be hidden with one switch for GDPR (hideAuthorNames). A keyed author_hash is always output; avatars, profile URLs and raw reviewer ids never are. Company replies are the company's own text, as written. Emails and phone numbers typed into a review are redacted.

What is Trustpilot Reviews Scraper?

It has two routes, chosen with the mode input:

  • Fast: Trustpilot's public widget data (widget.trustpilot.com/trustbox-data/, which that host's robots.txt allows). No browser and, normally, no proxy. It returns the newest ~100 reviews per star rating and language, without company replies, useful votes or reviewer country. Trustpilot only serves this widget data for companies on a paid Trustpilot plan; for every other company the Actor switches to the deep route automatically and remembers it for 30 days.
  • Deep: the full profile pages, described below. Every field and up to 2000 reviews per company and language, but slower, and it uses a residential proxy.
  • Auto (default): the widget first; the deep route only when you ask for more reviews than the widget gives, or for fields it lacks (withRepliesOnly, reviewerCountries).

Widget rows are marked ext_route = "widget"; profile-page rows ext_route = "browser". In widget rows developer_reply, developer_reply_at, helpful_count, country, ext_updated_at, ext_business_categories, ext_business_is_claimed and ext_business_review_count_12m are null (the widget does not carry them) and author_hash is null (it has no stable reviewer id); author_name is still the published display name. The first time a company is scraped, the Actor loads one profile page to learn its Trustpilot id; it is then cached in the named key-value store rastriq-trustpilot-bu-ids of your account.

The deep route: Trustpilot protects its pages with a JavaScript connection check. This Actor opens each public company page in a real headless browser, lets the page finish its own check, and reads the review data the page ships with. It opens the first page of each company in the browser and reads the next pages over a lighter HTTP connection in the same session, which keeps runs fast and cheap. It never solves CAPTCHAs and only requests the two page forms Trustpilot's robots.txt allows: /review/<domain> and /review/<domain>?page=N.

It shares one output contract with App Store Reviews Scraper and Google Play Reviews Scraper, so you can ingest all three sources with a single integration.

What data does Trustpilot Reviews Scraper extract?

FieldWhat it is
⭐ ratingStars, 1 to 5
📝 title, textReview title and body (emails and phones redacted)
🕒 published_atPublication time, ISO 8601, UTC
💬 developer_reply, developer_reply_atThe company's reply, exactly as written, and when it was posted, or null
👍 helpful_countUseful votes
🌍 lang, countryReview language and the reviewer's country (null when Trustpilot shows none). It is not a filter
🏷️ app_id, app_nameCompany domain as Trustpilot knows it and company display name
🔑 review_idDurable review id, used to deduplicate
👤 author_nameReviewer display name. null if you enable Hide author names
🔒 author_hashKeyed HMAC-SHA256 pseudonym of the reviewer id. Stable across runs while the salt is unchanged
🔗 source_url, scraped_atThe Trustpilot page that was read, and extraction time (UTC)
➕ ext_experienced_at, ext_review_verified, ext_review_source, ext_updated_atDate of the experience, verified label, how the review was collected, last update
🏢 ext_business_trust_score, ext_business_stars, ext_business_review_count, ext_business_review_count_12mThe company's TrustScore, stars, total reviews and reviews of the last 12 months when the page was read
🏬 ext_business_id, ext_business_website, ext_business_country, ext_business_categories, ext_business_is_claimedCompany profile data: Trustpilot id, website, country, category names and whether the profile is claimed (null when Trustpilot gives none)
✅ ext_review_verification_levelTrustpilot's verification level of the review (for example not-verified)
🌐 ext_language_requestedThe languages code this row was collected under
🛣️ ext_routewidget (fast route) or browser (full profile pages)
🚩 _quality_*Flags for missing text, rating or date. Flagged, never filtered

app_version is always null (Trustpilot reviews have no version). Fields the source does not provide are null, never invented.

How to scrape Trustpilot reviews with Trustpilot Reviews Scraper

  1. Open Trustpilot Reviews Scraper on Apify and click Try for free.
  2. In Companies, add domains such as www.booking.com or profile URLs such as https://www.trustpilot.com/review/booking.com.
  3. Set Max reviews (per company and language, 20 per page, newest first).
  4. Optionally pick Review languages, a Date range or Reviews since (the run stops as soon as a whole page is older) and any of the filters.
  5. Click Start and download the results as JSON, CSV, Excel or XML, or read them through the API.

Input parameters

ParameterTypeDescription
companiesarray, requiredDomains or Trustpilot profile URLs. Invalid entries are skipped and listed in the run summary
modestringauto (default: widget first, deep only when needed), fast (widget only: newest ~100 reviews per star rating and language; an input error if withRepliesOnly or reviewerCountries is set) or deep (full profile pages in a browser)
maxReviewsintegerMax reviews delivered per company and per language. If empty, 100. Hard cap 2000
languagesarrayLanguages to collect, from Trustpilot's localized sites: all (every language below, English first), en, de, fr, es, it, nl, da, sv, nb (no also accepted), fi, pl, pt, ja. If empty, en. Unsupported codes are skipped and listed in the run summary
dateRangestringlast30days, last3months, last6months or last12months, counted from today (UTC). Empty = any time. If dateFrom is also set, the later date wins
dateFromdate YYYY-MM-DDOnly reviews published on or after this date (UTC)
starsarrayOnly these star ratings (1 to 5). Empty = all
verifiedOnlybooleanOnly reviews Trustpilot labels as verified (ext_review_verified is true)
withRepliesOnlybooleanOnly reviews with a company reply (developer_reply is not null)
keywordstring, max 100Only reviews whose title or text contains it (case-insensitive)
reviewerCountriesarrayOnly reviews whose reviewer country is one of these ISO 3166 alpha-2 codes (case-insensitive)
incrementalKeystring [A-Za-z0-9-], max 40Only reviews newer than the previous run with the same key. State is kept per company and language in the named key-value store rastriq-trustpilot-incremental
hideAuthorNamesbooleanIf on, author_name is null in every row (GDPR). Default off

Example input

{
"companies": ["www.booking.com"],
"maxReviews": 100,
"languages": ["en", "de"],
"stars": ["1", "2"],
"dateRange": "last3months"
}

Output example

{
"review_id": "000000000000000000000001",
"store": "trustpilot",
"app_id": "www.example.com",
"app_name": "Example",
"country": "gb",
"lang": "en",
"rating": 2,
"title": "Support never answered",
"text": "I wrote three times and nobody replied.",
"author_hash": "3f1c0c5a0a6d6b7e9d2b8f4c1a7e5d3b9c0f2a6e8d4b1c7a5e3f9d0b2c4a6e81",
"author_name": "Reviewer 1",
"app_version": null,
"published_at": "2026-11-09T15:42:15Z",
"developer_reply": "Thank you for your feedback. Please contact our support team.",
"developer_reply_at": "2026-11-09T16:30:00Z",
"helpful_count": 0,
"source_url": "https://www.trustpilot.com/review/www.example.com",
"scraped_at": "2026-11-09T18:00:00Z",
"ext_pii_redactions": 0,
"ext_sort": null,
"ext_author_hash_weak": false,
"ext_experienced_at": "2026-11-09T00:00:00Z",
"ext_review_verified": false,
"ext_review_source": "Organic",
"ext_updated_at": null,
"ext_business_trust_score": 3.1,
"ext_business_stars": 3,
"ext_business_review_count": 1234,
"ext_business_id": "46d3f1f8000064000500b592",
"ext_business_website": "https://www.example.com",
"ext_business_country": "nl",
"ext_business_categories": ["Travel Agency"],
"ext_business_is_claimed": true,
"ext_business_review_count_12m": 321,
"ext_review_verification_level": "not-verified",
"ext_language_requested": "en",
"_quality_missing_text": false,
"_quality_missing_rating": false,
"_quality_missing_published_at": false,
"_quality_missing_app_name": false,
"_quality_bad_number": false,
"_quality_pii_redacted": false
}

Every run also writes a SUMMARY record with, for each company: reviews scanned, emitted and dropped, pages read, browser sessions used, Trustpilot's own total count and the reason it stopped.

Limits

  • Languages come from Trustpilot's localized sites. languages loads each company from de.trustpilot.com, fr.trustpilot.com and so on, which show only the reviews written in that language. Each company-language pair is its own group in the summary with its own maxReviews quota, and takes its own browser session. If Trustpilot already told us a company has no reviews in a language, that group ends without loading a page. If Trustpilot serves another language than requested, rows are kept and a note is added to the summary.
  • Other filters are applied after download. stars, verifiedOnly, withRepliesOnly, keyword and reviewerCountries never change the URL: the Actor reads the pages and keeps the matching reviews. Only delivered reviews are charged, but a strict filter has to read more pages. Each company-language group stops at a scan limit of about five times the pages maxReviews would need (at least 10, at most 200 pages) and says so in the summary notes. Filtered-out reviews are counted as filtered in the summary, not as losses.
  • Not supported, because robots.txt disallows it: sort by relevance or any ?sort=, topics, searching inside a company's reviews, Trustpilot's own star/verified/reply filters, company search, and review transparency pages. Reviews are always newest first.
  • Incremental runs remember, per company and language, the newest review delivered. If a run stops early (for example at maxReviews) older reviews it did not reach are not collected by later incremental runs; raise maxReviews or run more often. The marker only moves for groups that ended normally.
  • Fast route depth. The widget gives at most the newest 100 reviews per star rating and language (a request without a stars filter and maxReviews up to 100 is a single request; otherwise one request per star rating). Reviews older than the oldest review of a full request are not guaranteed complete, so they are not taken from the widget. In Fast mode the group then ends as widget_limit (not an error) with a note; in Auto the Actor continues with the deep route from the right page. A dateRange, dateFrom or incremental bound newer than that point is fully served by the widget.
  • Access levels. The widget is called directly (N0); if it answers 403/429/5xx, non-JSON or JSON without reviews it is retried once through the Apify datacenter proxy (N1); if that fails too it is skipped for the rest of the run and the deep route (N2) is used. levels_used in the summary lists the levels actually used.
  • How deep it goes. The deep route reads up to 200 pages (4000 reviews) per company and language, newest first, within your maxReviews (hard cap 2000). The fast route stops at about 100 reviews per star rating and language. If Trustpilot ever stops serving older pages, the run ends at that point with a note (public_page_limit) and still finishes successfully. Schedule it with incrementalKey or dateFrom to keep collecting new reviews as they arrive.
  • Polite by design: one page at a time, 1 to 3 seconds between pages. The first page of each company takes longer because a real browser passes the connection check.
  • If Trustpilot blocks a company, the Actor retries the page, then retries the company once with a fresh session, and finally marks it blocked in the summary. Reviews already delivered are kept. It never escalates to CAPTCHA solving.

How much does it cost to use Trustpilot Reviews Scraper?

Trustpilot Reviews Scraper uses pay-per-event pricing:

  • $0.30 per 1,000 reviews delivered (event review-record); $0.27 on the Silver plan and $0.24 on Gold and above.
  • $0.015 per company (event company-scraped), charged once per company per run, however many languages you pick, and only when the deep route (full profile pages) was used for that company. Companies served entirely by the fast route are not charged it.

For example, 1,000 reviews of one company cost $0.30 through the fast route and $0.315 through the deep route. Residential proxy traffic is included. Blocked or empty companies, duplicates, reviews older than dateFrom, reviews removed by your filters or already delivered in an incremental run, and invalid rows are never charged. Start with 20 reviews to see the exact bill, and set a maximum charge per run in the Apify Console to cap spending.

Privacy & GDPR

  • Reviewer name. author_name is the display name published with the review. To minimise personal data, switch on Hide author names (hideAuthorNames): every row then has author_name = null.
  • Author hash. author_hash is a keyed pseudonym: HMAC-SHA256 of the reviewer id, computed with the secret AUTHOR_HASH_SALT of the Actor. It is stable across runs while the salt does not change, so you can count repeat reviewers, but it is pseudonymisation, not anonymisation: whoever holds the salt can recompute it, and if no salt is set the Actor flags every row with ext_author_hash_weak = true.
  • Never output. Avatars, profile URLs and raw reviewer ids are never output, in either mode. Emails and phone numbers written inside the review text are redacted ([email], [phone]). Company replies are the company's own text, exactly as written.
  • Your responsibility. Review text is free text and may contain personal information. You remain responsible for your lawful basis, retention and use of the data under GDPR and Trustpilot's terms.

Trustpilot Reviews Scraper only collects review data that is publicly visible on Trustpilot.

FAQ

Does Trustpilot Reviews Scraper return company replies? Yes, in developer_reply and developer_reply_at, when the company answered, but only from the deep route. Widget rows (ext_route = "widget") do not carry replies; use mode: "deep", or set withRepliesOnly, which switches to the deep route in Auto. The field name is shared with the other stores in the suite.

Why is country sometimes null? It is the country shown with the reviewer, and Trustpilot does not always show one.

Can I filter by language or stars? Yes. languages uses Trustpilot's localized sites and stars (with verifiedOnly, withRepliesOnly, keyword, reviewerCountries) filters the reviews after download. See Limits for how filtered runs read pages and what is not supported.

How do I get only new reviews each day? Set an incrementalKey and schedule the Actor: each run delivers only reviews newer than the last run with that key. Alternatively schedule it with dateFrom or dateRange; reviews come newest first, so the run stops at the first page that is entirely older.

What happens if Trustpilot blocks the run? The run always ends cleanly with a SUMMARY record: completed, no_results, partial (some companies failed) or failed (all of them), with a stopped_reason per company.