# TrustRadius Reviews Scraper - Pros, Cons & TrustRadius Score (`lanternlab318/trustradius-reviews`) Actor

TrustRadius B2B software reviews by product URL or keyword: rating, pros, cons, use case and every public answer, reviewer role and company size (never names), plus TrustRadius Score, review count, vendor and category. No login or cookies. Partial results are marked, never shown as empty.

- **URL**: https://apify.com/lanternlab318/trustradius-reviews.md
- **Developed by:** [Lantern Lab](https://apify.com/lanternlab318) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.99 / 1,000 reviews

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## TrustRadius Reviews Scraper

A Lantern Lab Actor. Give it TrustRadius product URLs or product names and get the public B2B software reviews back: rating, title, **pros, cons**, use case and every other public answer, with the reviewer's job role, department, company size and industry. Each product also gets its **TrustRadius Score**, published review count, vendor and category. No TrustRadius login, no cookies, no browser.

**Price:** you pay per review collected. Product rows, status rows and the run summary are free, and so is a URL or search term that finds nothing.

### Quick example

Input:

```json
{
  "productUrls": ["https://www.trustradius.com/products/slack/reviews"],
  "searchQueries": ["hubspot crm"],
  "maxReviewsPerProduct": 100,
  "sort": "recent"
}
```

One review row (`recordType: "review"`, shortened):

```json
{
  "recordType": "review",
  "reviewId": "68dedb3b356a202e1e15e5a4",
  "reviewUrl": "https://www.trustradius.com/reviews/slack-2025-10-02-15-06-12",
  "productName": "Slack",
  "rating": 10,
  "title": "Slack review after 4 years",
  "pros": "Corporate chat\nCorporate announcements\nTriggered communications",
  "cons": "The reply feature: sometimes information get lost and people don't always know how to use it (discoverability problem)\n...",
  "text": "- Corporate chat\n - Corporate communication \n- Corporation organization of key documents ...",
  "reviewerJobType": "Manager",
  "reviewerDepartment": "Product Management",
  "companySize": "51-200 employees",
  "companyIndustry": "Computer Software",
  "yearsExperience": 4,
  "publishedAt": "2025-10-16T13:33:57.302Z",
  "partial": false,
  "collectedAt": "2026-10-23T16:03:38.970Z"
}
```

One product row (`recordType: "product"`, free):

```json
{
  "recordType": "product",
  "name": "Slack",
  "vendor": "Salesforce",
  "category": "Collaboration",
  "trScore": 9,
  "reviewCount": 642,
  "ratingsCount": 10272,
  "url": "https://www.trustradius.com/products/slack/reviews",
  "reviewsAvailable": 642,
  "reviewsReturned": 100,
  "partial": false,
  "statusText": "Collected 100 review(s) of 642 published."
}
```

### Limits

- Public data only. The reviewer's name, company name, LinkedIn profile and photo are never collected, even where TrustRadius shows them.
- Up to 10,000 reviews per product (TrustRadius' own paging limit; the largest product we measured, Miro, has about 6,400).
- TrustRadius' firewall refuses a search term that looks like a script (for example `<script>...`). That term is marked `partial` with `blocked`, never reported as having no match. Accents, `&`, quotes and `%` work.
- A brand name such as `salesforce` matches many of that vendor's products equally well. The Actor then takes the one with the most published reviews among the first five equal matches, which is not always the flagship. For a specific product, give its URL.
- English-language TrustRadius only; it has no other language editions. A search term in another language usually matches nothing, and the run says so.
- No vendor responses, screenshots, pricing tables or comparison pages.
- No scheduling or monitoring built in; use Apify schedules.

### What it does

- Accepts product URLs (`https://www.trustradius.com/products/<product>/reviews`, with or without `/reviews`, or just the slug) and search terms. A search term collects its best match, or its best few with `maxProductsPerQuery`.
- Returns pros, cons and the use-case answer as their own fields, plus `sections`: every public question the reviewer answered (ROI, alternatives considered, usability, ...) in page order.
- Deduplicates across the whole run: a product reached by both a URL and a search term is collected once, and a review is written and charged once.
- Keeps the source identifier (`reviewId`), the platform's publish and update times (`publishedAt`, `updatedAt`) and our collection time (`collectedAt`) as separate fields.
- Says what happened to every input and product. A product with no reviews, a URL that is not a product, and a product that was cut short are different records and are never confused: a cut-short product is marked `partial: true` with the reason.
- Gets past exit-IP refusals: TrustRadius' Cloudflare refuses some exit IPs outright, mostly datacenter ones. When that happens the run moves to a fresh Apify Proxy session (a new IP) and repeats the request, at most 5 times per request; `RUN_SUMMARY.proxySessionRotations` says how often. With the proxy turned off there is nothing to rotate, and a refusal is reported as `blocked`.
- Caps itself: `maxUpstreamRequests` is a hard ceiling on requests to TrustRadius for the whole run, derived from your input when you leave it empty, so a run is never unbounded.

### Input

| Field | Default | Meaning |
| --- | --- | --- |
| `productUrls` | — | TrustRadius product URLs or slugs, one per line. |
| `searchQueries` | — | Product names or keywords, one per line. Give at least one URL or one term. |
| `maxReviewsPerProduct` | `100` | Upper bound on reviews per product. `0` collects only the product profile. Max 10,000. |
| `maxProductsPerQuery` | `1` | How many best-matching products each search term collects (max 25). |
| `sort` | `recent` | `recent`, `positive` (highest rated first) or `critical` (lowest rated first). Decides which reviews a limit keeps. |
| `maxUpstreamRequests` | derived | Hard ceiling on requests to TrustRadius for the whole run. |
| `proxyConfiguration` | Apify residential, US | The proxy the requests go through. Residential is what this Actor is measured on; datacenter is cheaper but TrustRadius refuses a varying share of datacenter IPs. |

### Output

One row per review, `recordType: "review"`, charged:

| Field | Meaning |
| --- | --- |
| `reviewId`, `reviewUrl` | TrustRadius' own review ID (the dedupe key) and the public review page. |
| `productId`, `productName`, `productSlug` | The product reviewed. |
| `rating` | Overall rating on TrustRadius' 1-10 scale. |
| `title` | The review headline. |
| `pros`, `cons` | The reviewer's Pros and Cons answers. |
| `text` | The "Use Cases and Deployment Scope" answer. |
| `sections` | Every public answer: `{question, answer, comment}`. |
| `reviewerJobTitle`, `reviewerJobType`, `reviewerDepartment` | The reviewer's role, as published. Never the name. |
| `companySize`, `companyIndustry` | The reviewer's company profile, as published. Never the company name. |
| `yearsExperience` | Years the reviewer has used the product, when given. |
| `publishedAt`, `updatedAt` | When TrustRadius published and last updated the review. |
| `partial`, `partialReason` | Always `false` / `null` on a review row: the row exists because the review was collected. |
| `collectedAt` | Our own collection time. |

One row per product, `recordType: "product"`, free: `name`, `vendor`, `category`, `trScore` (the headline "Score N out of 10"), `reviewCount` (published full reviews - what this Actor collects), `ratingsCount` (the headline "N Reviews and Ratings", which also counts rating-only submissions that have no text), `likelihoodToRecommend` and `likelihoodToRecommendCount`, `url`, then `reviewsAvailable` / `reviewsRequested` / `reviewsReturned` / `duplicatesSkipped`, and `partial` / `partialReason` (`upstream_request_cap`, `charge_limit_reached`, `blocked`, `upstream_error`, `not_collected`) with `statusText`.

One row per product URL or search term, `recordType: "input_status"`, free: `outcome` is `found`, `not_found` (no such product, or no search match), `invalid_url` (not a TrustRadius product URL) or `partial`, with `productSlugs` and `statusText`.

The last row is `recordType: "RUN_SUMMARY"` — what the inputs resolved to, products and reviews collected and charged, products with no review, partial products by reason, requests sent by endpoint, and why collection stopped. The same object is also in the run's key-value store under `RUN_SUMMARY`.

# Actor input Schema

## `productUrls` (type: `array`):

TrustRadius product pages, one per line, for example https://www.trustradius.com/products/slack/reviews. The /reviews suffix is optional, and a bare product slug such as "slack" also works. A URL that is not a TrustRadius product URL, or a product that no longer exists, gets its own status row and is not charged.

## `searchQueries` (type: `array`):

Product names or keywords, one per line, for example "hubspot crm". Each term is searched on TrustRadius and its best match(es) are collected - see Max products per search term.

## `maxReviewsPerProduct` (type: `integer`):

Upper bound on the reviews collected for each product. 0 collects only the product profile (score, review count, vendor, category). TrustRadius pages reviews up to 10,000 per product.

## `maxProductsPerQuery` (type: `integer`):

How many of the best-matching products each search term collects. Product URLs are not affected.

## `sort` (type: `string`):

Which reviews come first, and so which ones a limit keeps.

## `maxUpstreamRequests` (type: `integer`):

Hard ceiling on the HTTP requests this run sends to TrustRadius. At the ceiling collection stops - what was not reached is written with partialReason "upstream_request_cap" and the run then ends normally. Leave empty and the Actor works a ceiling out from your input, so a run is never unbounded.

## `proxyConfiguration` (type: `object`):

The proxy the requests to TrustRadius go through. The default, Apify residential proxy with a US exit, is what this Actor is measured on: TrustRadius' Cloudflare refuses a varying share of datacenter IPs. Datacenter proxy is cheaper and usually works too - the run moves to a new IP when one is refused - but expect more refused requests.

## Actor input object example

```json
{
  "productUrls": [
    "https://www.trustradius.com/products/slack/reviews"
  ],
  "maxReviewsPerProduct": 100,
  "maxProductsPerQuery": 1,
  "sort": "recent",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `runSummary` (type: `string`):

No description

# 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 = {
    "productUrls": [
        "https://www.trustradius.com/products/slack/reviews"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("lanternlab318/trustradius-reviews").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 = {
    "productUrls": ["https://www.trustradius.com/products/slack/reviews"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("lanternlab318/trustradius-reviews").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 '{
  "productUrls": [
    "https://www.trustradius.com/products/slack/reviews"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call lanternlab318/trustradius-reviews --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lanternlab318/trustradius-reviews"
        }
    }
}
```

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/tryENKFgt0V7FgDgD/builds/HVJ53LwEGfMDRtOTu/openapi.json
