Scrape Trustpilot reviews for any company: rating, text, dates, reviewer, verified flag and company replies plus TrustScore and star distribution. For reputation monitoring and research.
AWS WAF challenge: Trustpilot now answers every plain HTTP request with HTTP 403 + a JavaScript challenge. The actor now solves it in Chromium (Playwright), reuses the aws-waf-token cookie with curl_cffi for fast requests, refreshes it automatically, falls back to in-browser fetch and to other proxy options (user proxy -> direct -> Apify RESIDENTIAL) when blocked.
Pagination: page count moved to filters.pagination – old code only ever read page 1.
Language filter: Trustpilot uses languages=; trustpilot.com defaults to English only. "all" now really returns all languages.
Run no longer fails when some companies are not found; problems are reported in RUN_SUMMARY. Fails only if 0 reviews AND a real error happened.
Empty input {} works (defaults to www.amazon.com , 100 reviews).
Added
Deep pagination beyond Trustpilot's 200-review public limit (split by language / stars / sort, de-duplicated).
Inputs: multiple star ratings ("1,2"), datePeriod (server-side), verifiedOnly, withRepliesOnly, searchKeyword, deepPagination; company names resolved via Trustpilot search; website URLs and country-subdomain URLs accepted.
New output fields (appended, existing names unchanged): company TrustScore, star distribution, categories, country, claimed flag, reply rate, logo; review has_owner_reply, date_updated, review_source, verification_level, reviewer_id, reviewer_image_url, input, scraped_at and more.
COMPANIES and RUN_SUMMARY key-value store records.
[1.1] – 2026-03-05
Fixed
Session not persistent — _fetch() was creating a new curl_cffi session for every request, so cookies were never carried between pages. Trustpilot saw each request as a cold first visit. Now a single session is created per business and reused across all its pages.
dateFrom/dateTo URL params silently ignored — Trustpilot's public pages ignore these query parameters. Filtering is now applied client-side on each parsed review's date_published field. When sort=recency and a review falls before dateFrom, scraping stops early (all later reviews will also be too old).
total_pages = 999 sentinel — caused unnecessary page requests for businesses with few reviews. Real pagination is now read from the first page's __NEXT_DATA__ before the loop continues.
No review deduplication — identical review IDs (or identical reviewer+date+text fingerprints) could appear multiple times. A seen_ids set now deduplicates reviews across pages.
reviewer_name defaulted to hardcoded "Anonymous" — now defaults to "" (empty string) consistent with other scrapers and the dataset schema.
Oversized Docker image — Dockerfile used apify/actor-python-playwright:3.11 (~1 GB extra) even though this scraper uses pure HTTP. Changed to apify/actor-python:3.11.
maxReviews=0 blocked by UI — INPUT_SCHEMA.json had "minimum": 1 preventing users from selecting unlimited mode via the Apify console. Changed to "minimum": 0.
Added
CHANGELOG.md created.
dataset_schema.json created with full field definitions.