How to use TrustRadius Reviews Scraper
Step by step: in the Apify Store, over the API, from JavaScript or Python, in n8n, and from AI agents through MCP or LangChain.
$3.59 per 1,000 reviews on the Free plan, down to $2.24 on higher plans (live Apify price on 2026-10-31).
1. In the Apify Store (no code)
- Open arcadium/trustradius-reviews and sign in to Apify (a free account works).
- Fill in the input form. The fields below are the ones the example uses.
- Set a maximum cost per run in the run options if you want a hard cap.
- Start the run. Rows appear in the Output tab as they arrive.
- Export the dataset as JSON, CSV or Excel, or connect an integration.
| Input field | Type | Description |
|---|---|---|
startUrls | array | Product pages such as https://www.trustradius.com/products/asana/reviews (the /reviews part is optional). A link to a single review also works and resolves to its product. Add this, product names, or both. |
maxReviewsPerProduct | integer | Maximum number of reviews to collect for each product (up to 50,000). Default: 100. |
sortBy | string | Sort reviews by date or by rating. Date with newest first enables the date filter and the incremental mode. Default: date. |
sortOrder | string | Descending is newest or highest rated first. Default: desc. |
Example input:
{
"startUrls": [
{
"url": "https://www.trustradius.com/products/asana/reviews"
}
],
"maxReviewsPerProduct": 20,
"sortBy": "date",
"sortOrder": "desc"
}
2. Over the Apify API
The synchronous endpoint runs the actor and returns its rows in one call (for runs up to about five minutes; use the asynchronous run endpoint for longer ones).
curl -X POST "https://api.apify.com/v2/acts/arcadium~trustradius-reviews/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"startUrls":[{"url":"https://www.trustradius.com/products/asana/reviews"}],"maxReviewsPerProduct":20,"sortBy":"date","sortOrder":"desc"}'
3. From JavaScript
// npm install apify-client
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('arcadium/trustradius-reviews').call({
"startUrls": [
{
"url": "https://www.trustradius.com/products/asana/reviews"
}
],
"maxReviewsPerProduct": 20,
"sortBy": "date",
"sortOrder": "desc"
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
4. From Python
# pip install apify-client
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("arcadium/trustradius-reviews").call(run_input={
"startUrls": [{
"url": "https://www.trustradius.com/products/asana/reviews",
}],
"maxReviewsPerProduct": 20,
"sortBy": "date",
"sortOrder": "desc",
})
items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items)
5. In n8n
Paste this node into a workflow (it is a plain HTTP Request node). Create a Header Auth credential with name Authorization and value Bearer <APIFY_TOKEN>; each returned row becomes one item for the next node.
{
"nodes": [
{
"name": "Run arcadium/trustradius-reviews",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
0,
0
],
"parameters": {
"method": "POST",
"url": "https://api.apify.com/v2/acts/arcadium~trustradius-reviews/run-sync-get-dataset-items",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "{\"startUrls\":[{\"url\":\"https://www.trustradius.com/products/asana/reviews\"}],\"maxReviewsPerProduct\":20,\"sortBy\":\"date\",\"sortOrder\":\"desc\"}",
"options": {
"timeout": 300000
}
}
}
],
"connections": {}
}
6. From an AI assistant (MCP)
Add Apify’s MCP server to Claude Desktop, Cursor, VS Code or any MCP client, limited to this actor:
{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com/?tools=arcadium/trustradius-reviews",
"headers": {
"Authorization": "Bearer <APIFY_TOKEN>"
}
}
}
}
More on the MCP page.
7. From LangChain
# pip install langchain-apify (reads APIFY_API_TOKEN from the environment)
from langchain_apify import ApifyActorsTool
tool = ApifyActorsTool("arcadium/trustradius-reviews")
rows = tool.invoke({"run_input": {
"startUrls": [{
"url": "https://www.trustradius.com/products/asana/reviews",
}],
"maxReviewsPerProduct": 20,
"sortBy": "date",
"sortOrder": "desc",
}})
# or give `tool` to an agent: create_react_agent(llm, [tool])
Sample output
One row, from the example in the actor’s README. Long text is shortened and lists are cut to two items.
{
"reviewId": "TrustRadius___638fcc80649f691b7696d9c6",
"platform": "trustradius",
"productName": "Asana",
"date": "2022-12-15",
"title": "Great task management tool",
"text": "Asana is used to manage all the internal activities at my company...",
"pros": "Receive requests\nDocument information\nManage tasks across departments",
"cons": "More free/not-premium features\nSmall navigation bugs\nTask templates",
"ratingOverall": 5,
"ratings": {
"likelihoodToRecommend": 10
},
"reviewerRole": null,
"reviewerCompanySize": null,
"reviewerTimeUsed": null,
"incentive": "TrustRadius",
"incentivized": true,
"extras": {
"jobType": "Manager",
"department": "Marketing",
"ratingRaw10": 10
}
}
| Field | What it holds |
|---|---|
rowType | Kind of row. Filter on this first. Values: 'review': one review (charged). 'coverage': stated total vs delivered and why reading stopped (free). 'error': an input could not be read; see code and message (free). |
platform | Source site, lower case, e.g. 'tripadvisor', 'capterra', 'googleplay', 'appstore'. |
productName | Name of the reviewed hotel, business, product or app. |
productUrl | Page of the reviewed hotel, business, product or app on the source site. |
entityId | The site's own id of the reviewed entity (place id, product id, app id). |
reviewId | Stable review id in the form '<Platform>___<native id>'. Use it to deduplicate between runs. |
reviewIdSource | 'native' when the id comes from the site, 'derived' when it is a hash of the content (less stable). |
reviewUrl | Link to the single review, null when the site has none. |
title | Review headline, null when the site has none. |
text | Review text in the language it was written in. Null when the review has no text. |
pros | What the reviewer liked, for sites that ask separately (Capterra, TrustRadius, Glassdoor, Booking). Null otherwise. |
cons | What the reviewer disliked, for sites that ask separately. Null otherwise. |
ratingOverall | Overall rating on a 0 to 5 scale (Booking: its 1-10 score divided by 2, original in extras.score10). Null when missing. |
ratings | Sub-ratings as an object, e.g. { value: 5, cleanliness: 4 }. Keys depend on the site; empty object when there are none. |
date | Date the review was written, ISO format yyyy-mm-dd. Null if unknown. |
reviewerRole | Job title or role the reviewer states. No names. Null if not given. |
reviewerIndustry | Industry the reviewer states. Null if not given. |
reviewerCompanySize | Company size bracket of the reviewer, e.g. '51-200 employees'. Null if not given. |
reviewerTimeUsed | How long the reviewer used the product, as the site words it. Null if not given. |
switchedFrom | Product the reviewer switched from, null if not given. |
alternativesConsidered | Alternatives the reviewer considered, comma-separated, null if not given. |
reasonForChoosing | Why the reviewer chose this product, free text, null if not given. |
reasonForSwitching | Why the reviewer left the previous product, free text, null if not given. |
adviceToOthers | Advice the reviewer gives others (Glassdoor: advice to management), null if not given. |
incentivized | True when the site marks the review as incentivized (for example a gift card). Null when the site does not say. |
incentive | The site's raw incentive label, null if none. |
reviewerVerified | True when the site marks the review as verified. Null when the site does not say. |
vendorResponse | Reply of the owner, vendor, developer or employer, null when there is none. |
helpfulVotes | Number of helpful or useful votes, null when the site shows none. |
language | Language of the review text as a two-letter code, null if unknown. |
country | Country of the reviewer or the storefront where it applies (lower case code), otherwise null. No personal data. |
product | Summary of the reviewed entity repeated on each row: { platform, entityId, name, url, rating, reviewCount, category, vendor, website }. rating and reviewCount are the site's overall figures. |
extras | Site-specific extras, e.g. trip type, visit date, translated text, photo URLs, owner reply date. Keys are listed in the README. |
scrapedAt | ISO timestamp of when the row was collected. |
stated | Coverage rows: total the site states for the entity, null when it does not say. |
delivered | Coverage rows: number of rows delivered for the entity in this run. |
skippedSeen | Coverage rows: items skipped because an earlier run already delivered them (only-new mode). |
duplicates | Coverage rows: repeats the site returned that were dropped. |
stopReason | Coverage rows: why reading stopped. limit (your maximum reached), end (no more pages), dateFrom (older than your date), onlyNew (reached already delivered items), budget (run charge limit), cap (site-side depth limit), error (ended by a failure), filter (ended with a filter active). |
capSource | Coverage rows: who limited the result, 'user' (your maximum or budget) or 'site' (a limit of the website). Null if nobody. |
shortfall | Coverage rows: true when fewer rows were delivered than the site states although no maximum or filter was set. |
input | Error and coverage rows: the input (URL, id or search text) the row is about. Example: 'https://www.example.com/page'. |
code | Error rows: machine-readable reason. One of invalid_input (fix the input), not_found (page does not exist), blocked (site refused, retry later), unavailable (temporary error, retry later), filter_unsupported (the filter cannot be applied on this site), no_match (name search found nothing). |
message | Error rows: short human-readable explanation. Do not parse it, use code. |
Schedule it
In Apify Console, create a Task from your input and add a Schedule (for example daily). Each run writes a new dataset; integrations can push the rows to Google Sheets, Slack, a webhook or your database.