Trustpilot Reviews API
Trustpilot company reviews as structured JSON, shaped for watching a rating move rather than reading it once. Three things make that possible: the date of experience is kept separate from the posting date, replies the business posted come back as structured entries rather than buried text, and every row carries the company's full 5-to-1 star split with an absolute count and a percentage share at each level. Send up to 200 company review URLs per run, pay per review returned, MCP-ready for Claude and other agents.
MEDIAN LAGon demand
FIELDS35
Input parameters
| PARAMETER | TYPE | REQ | DEFAULT | DESCRIPTION |
|---|---|---|---|---|
| companyUrls | string[] | yes | — | Company review-page URLs, for example https://www.trustpilot.com/review/example.com. A bare domain such as example.com works as shorthand. Up to 200 companies per run; anything past the cap is not collected. There is no keyword search or company discovery mode, so you build the company list and feed it in. |
| maxReviewsPerCompany | integer | no | 100 | Reviews returned per company, from 1 to 1000. The cap is applied at the source, so nothing beyond it is collected or billed, which makes this the ceiling on what a run can cost. — drives your bill |
| datePosted | enum | no | — | Restrict to reviews posted inside one recent window. The four accepted values are Last 30 days, Last 3 months, Last 6 months and Last 12 months. Leave it empty for all reviews. The source offers these fixed windows only, not calendar start and end dates, so a narrower slice means pulling the window that contains it and filtering afterwards. |
Output schema
| FIELD | TYPE | DESCRIPTION | NULLABLE |
|---|---|---|---|
| result_type | string | review or error, so a company URL that returned nothing stays visible in the same dataset instead of vanishing. | no |
| reviewId | string | Stable identifier for the review on the source site. Upsert on this to make a daily re-run idempotent. | no |
| reviewTitle | string | Headline the reviewer gave. Long titles arrive truncated the way the source truncates them. | yes |
| reviewContent | string | Full review body. | yes |
| reviewRating | integer | Star rating this reviewer gave, 1 to 5. | no |
| reviewDate | string | ISO 8601 timestamp of when the review was posted. | no |
| dateOfExperience | string | When the reviewer says the interaction actually happened. Frequently months earlier than the posting date, and usually the more meaningful axis for trend work. | yes |
| isVerifiedReview | boolean | Whether the source verified this review. | no |
| reviewUsefulCount | integer | How many people marked the review useful. | yes |
| reviewReplies | array | Replies the business posted to this review, each with its text and date. The key is absent entirely when there is no reply, which is what makes an unanswered-complaint filter a one-liner. | yes |
| reviewUrl | string | Direct link to the individual review. | no |
| summary | string | One-line plain-language digest of the row, for example: 5-star verified review of DuGood Credit Union by David Werner. Lets an agent read a record without post-processing. | no |
| reviewerName | string | Display name of the reviewer as shown publicly. | yes |
| reviewerLocation | string | Two-letter country code the reviewer posted from. Country only, nothing finer. | yes |
| reviewerTotalReviews | integer | How many reviews this person has posted overall, which is the weighting signal for telling an established reviewer from a one-time account. | yes |
| companyName | string | Name of the reviewed business. | no |
| companyUrl | string | The company review page this review came from. | no |
| companyWebsite | string | The business's own website. | yes |
| companyCategory | string | Primary category, returned as the source's own slug rather than a display label, for example credit_union. Use categoryPath for readable names. | yes |
| companyActivities | array | Every activity category the business is listed under, in display form. | yes |
| categoryPath | array | Category breadcrumb, broadest first, for example Money & Insurance, Credit & Debt Services, Credit Union. | yes |
| companyOverallRating | number | The business's headline star rating across all reviews. Repeated on every row, so a one-review pull still gives you the current score. | no |
| companyRatingLabel | string | Word form of the overall rating, for example Excellent. | yes |
| companyTotalReviews | integer | How many reviews the business has in total, which is the denominator the star percentages are computed against. | no |
| companyIsVerified | boolean | Whether the business itself is verified on the source site. Often false even for companies that publish full contact details. | no |
| starBreakdown | object | The 5-to-1 split as star5 through star1, each with a count and a percent. Kept as one object because the source's own keys cannot be camelCase field names. | no |
| companyEmail | string | Contact email the business publishes on its profile. Missing for plenty of companies. | yes |
| companyPhone | string | Contact phone the business publishes on its profile, in whatever format it typed. | yes |
| companyLocation | string | Address block as published, delivered as one unparsed string that sometimes repeats the email and phone before the street address. Treat it as text, not as structured address fields. | yes |
| companyCountry | string | Two-letter country code the business is registered in. | yes |
| companyAbout | string | The business's own description of itself, useful mainly as context for a model. | yes |
| companyLogo | string | Logo image URL. | yes |
| error_message | string | Plain-language reason a company URL produced no reviews. Present on error rows only. | yes |
| error_type | string | Machine-readable error category, for example CollectionError. Present on error rows only. | yes |
| fetched_at | string | UTC timestamp when the row was collected, which is what turns a stack of runs into a dated rating series. | no |
Worked examples
{
"companyUrls": ["https://www.trustpilot.com/review/www.dugood.org"]
}
{
"companyUrls": ["https://www.trustpilot.com/review/www.dugood.org"],
"maxReviewsPerCompany": 1
}
{
"companyUrls": ["https://www.trustpilot.com/review/www.dugood.org"],
"maxReviewsPerCompany": 200,
"datePosted": "Last 30 days"
}
{
"companyUrls": ["example.com", "competitor-one.com", "competitor-two.com"],
"maxReviewsPerCompany": 100
}
{
"companyUrls": ["https://www.trustpilot.com/review/www.dugood.org"],
"maxReviewsPerCompany": 1000
}
{
"companyUrls": ["example.com", "competitor-one.com"],
"maxReviewsPerCompany": 500,
"datePosted": "Last 3 months"
}
POWER-USER TIP
One review buys the entire rating distribution — Every review row repeats the company block, so maxReviewsPerCompany set to 1 returns companyOverallRating, companyTotalReviews and the full star5-to-star1 breakdown with counts and percentages for the price of a single review. That is the cheapest possible daily reputation ping across a large competitor list, and it is exactly what you want on a schedule once the backfill is done.
POWER-USER TIP
Bucket by dateOfExperience, not reviewDate — The two dates drift apart badly. In a verified run against a real company, one review posted on 2026-07-13 described an experience from 2025-08-07, and the next one posted 2026-06-03 described 2025-11-29. Charting complaints by posting date would have put both in the wrong quarter. Note the tradeoff: datePosted filters on the posting date, so an experience-date analysis needs the wider window pulled and filtered afterwards.
POWER-USER TIP
reviewReplies is absent, not empty — When a business never replied, the key is missing from the row rather than present as an empty list. Your unanswered-complaint filter is therefore an absence check, not a length check. In Python that is "not item.get('reviewReplies')" combined with a low reviewRating; in SQL, store a boolean has_reply at load time.
POWER-USER TIP
Cost is companies multiplied by reviews — Only maxReviewsPerCompany carries the cost-driver flag, but spend is the product of both inputs. A full 200 companies at the 1000-review ceiling is 200,000 billable reviews in one run. Set a run-level max charge on the platform before your first big backfill, and keep recurring runs on a datePosted window.
POWER-USER TIP
Company contact fields arrive as published, not parsed — companyLocation is a single string built from whatever the business typed, and in practice it can repeat the email and phone ahead of the street address. companyCategory comes back as the source's slug, not a display label. If you need clean geography or readable categories, use companyCountry and categoryPath instead of parsing those two.
Coverage
200
companies per run — review-page URLs or bare domains
1,000
reviews per company — capped at the source, never billed past the cap
5
star levels, each with count and percent — star5 · star4 · star3 · star2 · star1
35
fields per row — review · reviewer · company · star split · error
4
posted-within windows — 30 days · 3 months · 6 months · 12 months
2
dataset views — reviews overview · reputation snapshot
Tasks
Saved runs with the inputs already filled in — each one a standalone page and a working configuration example.
Written about this source
Walkthroughs, worked examples and posts about this source.
TASK
Get Trustpilot Reviews by API from Company URLs
TASK
Monitor Trustpilot Reputation for Any Company
TASK
Audit Trustpilot Reviews for Fake Review Signals
TASK
Build a Customer Review Dataset for Sentiment Analysis
TASK
Export Trustpilot Reviews to CSV for Any Company
TASK
Read Trustpilot Reviews in Claude via MCP
TASK
Monitor Competitor Trustpilot Ratings
TASK
Bulk Collect Trustpilot Reviews and Export to CSV
Code
curl
curl -X POST "https://api.apify.com/v2/acts/johnvc~trustpilot-reviews-api/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"companyUrls":["https://www.trustpilot.com/review/www.dugood.org"],"maxReviewsPerCompany":100,"datePosted":"Last 30 days"}'
Python
from apify_client import ApifyClient
client = ApifyClient("APIFY_TOKEN")
run = client.actor("johnvc/trustpilot-reviews-api").call(
run_input={
"companyUrls": ["https://www.trustpilot.com/review/www.dugood.org"],
"maxReviewsPerCompany": 100,
"datePosted": "Last 30 days",
}
)
for item in client.dataset(run.default_dataset_id).iterate_items():
if item.get("result_type") != "review":
print("skipped:", item.get("error_message"))
continue
# reviewReplies is absent, not empty, when nobody replied
unanswered = item["reviewRating"] <= 2 and not item.get("reviewReplies")
print(
item["reviewRating"],
item.get("dateOfExperience"),
item["reviewTitle"],
"UNANSWERED" if unanswered else "",
)
MCP
claude mcp add --transport http trustpilot \ "https://mcp.apify.com/?tools=actors,docs,johnvc/trustpilot-reviews-api"
Changelog
2026-08-08
0.0.8 Rebuilt to fix a dataset field type mismatch that could abort a push; MCP access re-verified against the hosted server.
2026-08-07
Published on the Apify Store with eight worked task pages and a monthly keep-alive run.
2026-08-05
Pay-per-review pricing set at launch, with volume tiers below the list rate.
What people use it for
- Reputation monitoring for your own brand
- Competitor rating and complaint tracking
- Finding negative reviews the business never answered
- Fake review and review quality auditing
- Customer sentiment analysis datasets
- Rating trend tracking and crisis early warning
- Feeding review context to an AI agent
Alternatives
G2 Reviews API — B2B software reviews, where the reviewer is a buyer at a company rather than a consumerours
Glassdoor Reviews API — employee reviews of the same business, which often explain why a customer rating slidours
Yelp Reviews API and MCP — local and physical-location reviews, the better fit for a multi-site retailerours
OpenTable Reviews API — restaurant reviews with a per-category rating split for food, service and ambienceours
Google AI Overview API — what AI search answers say about the brand, the other half of a reputation pictureours
Trustpilot's own developer API — official and authoritative for your own business profile, and the right choice when you only need your own data; it is gated behind a business account and scoped to that account, so it cannot read a competitorcompeting
Trustpilot Reviews Scraper by getwally.net — cheaper per review and enough when all you want is the review text; it returns no company replies, no verified flag, no date of experience and no company star breakdowncompeting