DEV Community

Nikita Iakovlev
Nikita Iakovlev

Posted on

Capterra and Software Advice Share One Review Database and Disagree by 13,058 Reviews

I run a visa agency in Bali. The half of my week that has nothing to do with visas goes into Apify Actors, and one of them collects B2B software reviews — Capterra, Software Advice, GetApp and TrustRadius — and returns every site with the same field names.

That last part started as a convenience feature — four scrapers, four field vocabularies, one translation layer I got tired of rewriting. What it turned into was a measuring instrument: once the rows line up you can put the sites side by side and see where they disagree. They disagree a lot, and not in the way I expected.

Here is the measurement. Product: Slack. Builds 0.1.39 and 0.1.40, runs on 13–15 October 2026, no proxy.

Three sites, one database, three different totals

Ask for Slack on Capterra, Software Advice and TrustRadius, ten reviews each, and the product header on those rows reads:

source           productReviewCount   productRating   ratingScale
capterra                     11,166          4.4643            5
softwareadvice               24,224          4.6639            5
getapp                       24,224          4.6639            5
trustradius                  10,268               9           10
Enter fullscreen mode Exit fullscreen mode

Software Advice and GetApp agree to four decimal places. Capterra — the biggest brand of the three, the one whose logo everyone recognises — reports 11,166 reviews and an average two tenths of a star lower.

My first guess was that these are simply three separate review pools that happen to overlap in subject matter. That guess is wrong, and the reviewId field is what killed it:

softwareadvice  Capterra___7219769
softwareadvice  Capterra___7224596
getapp          Capterra___7138404
capterra        Capterra___7209002
Enter fullscreen mode Exit fullscreen mode

Those are reviews scraped from softwareadvice.com and getapp.com. They carry Capterra identifiers because all three sites are Gartner properties running on one review database. The IDs interleave, too — 13 of the 20 Software Advice IDs I collected fall inside the numeric range of the 45 Capterra IDs. It is one sequence, handed out to one pool of reviews, served through three front doors with three different filters on the way out.

So the 13,058-review gap is not a data gap. It is an editorial decision about which of the shared reviews each brand chooses to display, and it is invisible if you scrape one site.

The same review, twice, with a different reviewer on it

Across 45 Capterra reviews and 20 Software Advice reviews I caught exactly one ID on both sites: Capterra___7224596. Field by field:

field                     capterra                softwareadvice
title                     "Slack is the best…"    "Slack is the best…"   same
publishedAt               2026-10-04              2026-10-04             same
pros / cons               identical text          identical text         same
overallRating             5                       5                      same
easeOfUseRating           5                       5                      same
functionalityRating       5                       5                      same
valueForMoneyRating       5                       5                      same
customerSupportRating     4                       4                      same
incentivized              true  (NominalGift)     true  (NominalGift)    same
reviewerIndustry          Construction            Construction           same
--
reviewerName              "Chris S."              "Chris S——" (full)     differs
reviewerJobTitle          "General Manager"       null                   differs
reviewerCompanySize       "51-200 employees"      null                   differs
reviewerCompanySizeCode   null                    "D"                    differs
timeUsed                  null                    "More than 2 years"    differs
usageFrequency            null                    "Daily"                differs
Enter fullscreen mode Exit fullscreen mode

Everything a reviewer typed is byte-identical. Everything about the reviewer is split between the two pages. Capterra publishes the job title and a readable company-size range and abbreviates the surname to an initial. Software Advice publishes the reviewer's full first and last name — I'm redacting it here, since the point is the disclosure difference and not this person — drops the job title, and replaces the company-size range with a single letter.

That letter is worth a paragraph of its own. Software Advice and GetApp publish A through I where Capterra publishes 11-50 employees, and neither site publishes a legend. The temptation is to map it yourself: A is surely the smallest bucket, I the largest, nine letters for nine ranges. I didn't, because on this one shared review the letter is D and the range Capterra prints for the same company is 51-200 employees — a single data point, enough to build a guess on and nowhere near enough to ship one. So the Actor passes the letter through in reviewerCompanySizeCode and leaves reviewerCompanySize empty. One confirmed pair is a hint, not a mapping.

What this does to de-duplication

If you are merging Capterra, Software Advice and GetApp, reviewId is a real join key and you should use it. But the merge is not idempotent in either direction, because neither row is a superset of the other. Prefer the Capterra row and you lose usageFrequency and timeUsed. Prefer the Software Advice row and you lose the job title and the human-readable company size. The only correct merge is field-level: for each column, take whichever side is non-null.

TrustRadius stays out of this entirely. Its IDs are slugs with a timestamp — slack-2026-08-05-00-29-43 — its reviewers are its own, and across ten rows it returned zero sub-ratings while filling in reviewerJobTitle on all ten ("Full-stack developer", "Sr. Director engineering", "Senior Salesforce Administrator"). Different site, different database, genuinely additive sample.

And GetApp is no longer a review source in any useful sense. Its product totals are complete and match Software Advice exactly, but the product page now publishes about six short quotes instead of full reviews, with no ratings at all. Of the five rows I got back, three had pros filled and cons empty, two the reverse — the page quotes one half of each review and doesn't say which half. The first one reads "However, managing constant notifications can be overwhelming at times…", which is a complaint, sitting in a field called pros, because that is the only text GetApp published for it. Use GetApp for product-level numbers; don't build a sentiment set from it.

Page one is not a sample

One more thing I only saw because the rows lined up. Ten reviews from each site, in the order the site publishes them, no sort, no filter:

capterra         5 5 3 3 4 5 5 4 4 5     avg 4.3
softwareadvice   5 5 5 5 5 5 5 5 5 5     avg 5.0
Enter fullscreen mode Exit fullscreen mode

Same database. Software Advice's front page was a wall of five stars; Capterra's front page was not. Five of those ten Software Advice reviews were flagged incentivized — NominalGift or VendorReferredIncentivized — against 14 of 45 on Capterra.

The low ratings do exist in the shared pool, they are just not on page one. Asking for them explicitly finds them:

{
  "searchTerms": ["Slack"],
  "searchSites": ["softwareadvice"],
  "maxRating": 3,
  "maxReviews": 10
}
Enter fullscreen mode Exit fullscreen mode

Ten rows: nine 3-star and one 1-star, the oldest from 2025-10-31, six of the ten incentivized. The filter runs while paging rather than after it, so the run keeps reading pages until it has what you asked for or the site runs out:

def matches_filters(row, *, min_rating, max_rating, published_after, published_before):
    # TrustRadius rates out of 10, the Gartner sites out of 5, so filtering happens on
    # the normalized 1-5 value the user is thinking in.
    rating = row.get('normalizedRating', row.get('overallRating'))
Enter fullscreen mode Exit fullscreen mode

That normalization is why maxRating: 3 means the same band of unhappy customers on TrustRadius as on Capterra. overallRating keeps the site's own number, ratingScale says which scale it was, normalizedRating is raw * 5 / scale. A TrustRadius 9 arrives as overallRating: 9, ratingScale: 10, normalizedRating: 4.5, and averaging that against a Capterra 5 is finally a legal operation.

Calling it

Search by name on Software Advice and TrustRadius, by URL on Capterra and GetApp — Capterra's search page refuses automated requests even through a residential proxy, and GetApp publishes no search page at all. Their product pages are served normally, so a URL is all you need:

curl -X POST "https://api.apify.com/v2/acts/lergassy~software-reviews-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "productUrls": ["https://www.capterra.com/p/135003/Slack/reviews/"],
    "searchTerms": ["Slack"],
    "searchSites": ["trustradius", "softwareadvice"],
    "maxReviews": 200,
    "includeProductRow": true
  }'
Enter fullscreen mode Exit fullscreen mode

Thirty reviews across three sites took 46 seconds; thirty from Capterra alone took 90, because reviews come 25 to a page and each page is a request. Budget roughly three to four seconds per page. The Actor is here if you want to run the comparison on your own category — pricing is per row, $0.0012 a review and $0.003 a product summary, and failed URLs come back as error rows at no charge.

When not to use this

Don't use it to count. If you need "how many reviews does this product have", you now know that question has two different right answers depending on which Gartner brand you ask, and any single number you quote is a brand's choice rather than a fact.

Don't use it for G2 — different site, different gate, not covered here. And if what you want is volume over time, note that publishedAt is reliable but the sites' own ordering is not chronological, so a date histogram needs the full history pulled, not a recent slice.

Do use it when the comparison is the point: the same product across four sites, the same columns, and a normalized rating that makes an average mean something. Just merge field-level, and treat page one as a storefront rather than a sample.

Top comments (0)