# Capterra Reviews Scraper - Ratings, Pros & Cons, Reviewer Role (`lanternlab318/capterra-reviews`) Actor

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

## Pricing

$0.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

## Capterra Reviews Scraper

Give it Capterra product URLs and get the public software reviews back: star rating and the four sub-ratings, title, **pros, cons** and overall comments, with the reviewer's **job title, industry and company size** (never the name). Each product also gets its Capterra rating, published review count, vendor and category. No Capterra login, no cookies of yours.

**Price:** $0.99 per 1,000 reviews. Product rows, input status rows and the run summary are free, and so is a URL that finds nothing.

### Quick example

Open the product on [capterra.com](https://www.capterra.com) and copy its link from the address bar: `https://www.capterra.com/p/<id>/<name>/`, with or without `reviews/` at the end.

Input:

```json
{
  "productUrls": [
    "https://www.capterra.com/p/135003/Slack/reviews/",
    "https://www.capterra.com/p/156777/CRM-Pro/"
  ],
  "maxReviewsPerProduct": 25
}
```

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

```json
{
  "recordType": "review",
  "reviewId": "7209002",
  "productName": "Slack",
  "rating": 5,
  "easeOfUseRating": 5,
  "customerServiceRating": 5,
  "functionalityRating": 5,
  "valueForMoneyRating": 5,
  "likelihoodToRecommend": 10,
  "title": "Slack: Essential for remote work productivity...and employee engagement",
  "pros": "Since 2020, I've worked remotely as a business developer across two digital services companies. ...",
  "cons": "Honestly, not much. The only time I get frustrated with it is when I need to invite partners ...",
  "text": "Slack has been part of the corporate toolkits of the companies I've worked for since 2017 ...",
  "reviewerJobTitle": "Director, Business Development",
  "reviewerIndustry": "Information Technology and Services",
  "companySize": "201-500 employees",
  "timeUsedProduct": "2+ years",
  "incentive": "none",
  "publishedAt": "2026-09-03",
  "partial": false,
  "collectedAt": "2026-10-24T09:12:40.118Z"
}
```

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

```json
{
  "recordType": "product",
  "productId": "135003",
  "name": "Slack",
  "vendor": "Slack",
  "category": "Team Communication Software",
  "overallRating": 4.7,
  "reviewCount": 24230,
  "url": "https://www.capterra.com/p/135003/Slack/",
  "reviewsReturned": 25,
  "signInRequiredForMore": true,
  "partial": false,
  "statusText": "Collected 25 review(s) of 24230 published."
}
```

### Limits

- **Popular products: the first 25 reviews only.** On many popular products (Slack, Salesforce, Discord, ...) Capterra shows a visitor who is not signed in the first page of reviews only - page 2 and later open a sign-in prompt. This Actor does not sign in, so for those products it collects that first page (25 reviews, Capterra's "Most Helpful" order). If you ask for more, the product row says so: `partial: true`, `partialReason: "sign_in_required"`. Products without that prompt are paged through up to `maxReviewsPerProduct`.
- **One order: Most Helpful.** Capterra's other orders and its filters also sit behind the sign-in prompt.
- Public data only. The reviewer's name, initials and photo are never collected, even where Capterra shows them.
- capterra.com (the US/English site) only.
- Runs a real browser on Apify Proxy residential IPs, because Capterra refuses plain HTTP clients and datacenter IPs.
- No scheduling or monitoring built in; use Apify schedules.

### What it does

- Accepts product URLs (`https://www.capterra.com/p/<id>/<product>/`, with or without `reviews/`). There is no keyword search: find the product on Capterra and copy its link.
- Reads both page layouts Capterra serves today (large and small products) into one output shape.
- Deduplicates across the whole run: a product given twice (any slug, with or without `reviews/`) is collected once, and a review is written and charged once.
- Keeps Capterra's review ID (`reviewId`), the review date (`publishedAt`, a day) 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.
- Caps itself: `maxUpstreamRequests` is a hard ceiling on page requests to Capterra for the whole run, derived from your input when you leave it empty, so a run is never unbounded.

### Input

| Field | Default | Meaning |
| --- | --- | --- |
| `productUrls` | — | Capterra product URLs, one per line. At least one. |
| `maxReviewsPerProduct` | `100` | Upper bound on reviews per product. `0` collects only the product profile. Max 10,000. |
| `sortBy` | `most_helpful` | Capterra's default order; the only one available without sign-in. |
| `maxUpstreamRequests` | derived | Hard ceiling on page requests to Capterra for the whole run. |
| `proxyConfiguration` | Apify Proxy, residential, US | The proxy the browser goes through. |

### Output

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

| Field | Meaning |
| --- | --- |
| `reviewId` | Capterra's own review ID (the dedupe key). |
| `productId`, `productName`, `productSlug` | The product reviewed. |
| `rating` | Overall rating, 1-5 stars. |
| `easeOfUseRating`, `customerServiceRating`, `functionalityRating`, `valueForMoneyRating` | Sub-ratings, 1-5; `null` when the reviewer skipped one. |
| `likelihoodToRecommend` | 0-10. |
| `title`, `pros`, `cons`, `text` | The headline, the Pros and Cons answers, and the overall comments. |
| `reasonsForChoosing`, `reasonsForSwitching` | When the reviewer answered them. |
| `reviewerJobTitle`, `reviewerIndustry`, `companySize`, `timeUsedProduct` | The reviewer's profile, as published. Never the name. Small products' pages do not publish a company size. |
| `incentive` | Whether the reviewer was offered something for the review (`none`, `Nominal gift`, ...), as Capterra labels it. |
| `vendorResponse` | The vendor's public reply, when there is one. |
| `publishedAt` | The review date Capterra shows (`YYYY-MM-DD`). |
| `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` (when Capterra names one), `category`, `overallRating`, `reviewCount`, `url`, then `reviewsAvailable` / `reviewsRequested` / `reviewsReturned` / `duplicatesSkipped`, `signInRequiredForMore`, and `partial` / `partialReason` (`sign_in_required`, `upstream_request_cap`, `charge_limit_reached`, `blocked`, `upstream_error`, `not_collected`) with `statusText`.

One row per product URL, `recordType: "input_status"`, free: `outcome` is `found`, `not_found` (no such product), `invalid_url` (not a Capterra product URL) or `partial`, with `productIds` 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, 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`):

Capterra product pages, one per line. Open the product on capterra.com and copy the link from the address bar: https://www.capterra.com/p/<id>/<name>/, with or without /reviews/ at the end - for example https://www.capterra.com/p/135003/Slack/reviews/. A URL that is not a Capterra product URL, or a product that no longer exists, gets its own status row and is not charged.

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

Upper bound on the reviews collected for each product. 0 collects only the product profile (rating, review count, vendor, category). Popular products show only their first 25 reviews to a visitor who is not signed in - see the README.

## `sortBy` (type: `string`):

Which reviews come first, and so which ones a limit keeps. Capterra's other orders (most recent, by rating) need a Capterra sign-in, which this Actor does not do.

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

Hard ceiling on the page requests this run sends to Capterra. 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 browser goes through. Capterra refuses datacenter IPs, so the default is Apify Proxy residential, United States - what this Actor is measured on.

## Actor input object example

```json
{
  "productUrls": [
    "https://www.capterra.com/p/135003/Slack/reviews/"
  ],
  "maxReviewsPerProduct": 100,
  "sortBy": "most_helpful",
  "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.capterra.com/p/135003/Slack/reviews/"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("lanternlab318/capterra-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.capterra.com/p/135003/Slack/reviews/"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lanternlab318/capterra-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/4mI4XmSTvV2tS1KD4/builds/Ml02uiPnqMQec0SXr/openapi.json
