Steam Reviews Scraper avatar

Steam Reviews Scraper

Pricing

from $1.26 / 1,000 results

Go to Apify Store
Steam Reviews Scraper

Steam Reviews Scraper

User reviews for any Steam game, with the playtime, purchase source and vote counts Steam attaches to each. Never stops on a short page - Steam serves 99-row pages mid-stream, and a walker that treats one as the end returns 1,499 of 5,236,483 reviews and reports success.

Pricing

from $1.26 / 1,000 results

Rating

0.0

(0)

Developer

Ibnu Adzim

Ibnu Adzim

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

Every user review for any Steam game, with the playtime, purchase source, language and vote counts Steam attaches to each one. Straight from store.steampowered.com/appreviews — no login, no API key, no browser.

The thing that makes this different: it doesn't stop early

Steam serves short pages in the middle of the stream. Walking Counter-Strike 2 with 100 reviews per request:

page 15 -> 99 reviews, and ALL 99 WERE NEW
page 29 -> 99 reviews, and ALL 99 WERE NEW
... the stream kept going well past page 30

The obvious stop condition — "fewer rows came back than I asked for, so that was the last page" — is wrong here, and it fails silently and catastrophically: a scraper using it stops at page 15 with 1,499 reviews of the 5,236,483 the same response says exist, and reports success. The first draft of this actor's own recon walker did exactly that.

This actor never stops on a short page. It counts them (shortPagesSeen) and keeps going, stopping only on an empty page, a cursor that stops advancing, a page with no new IDs, or your own maxReviewsPerApp. Which one ended the run is reported in stopReason.

Steam's own default hides 46.7% of the reviews

purchase_type defaults to steam upstream, which excludes keys activated outside Steam. Measured on CS2 in one minute:

purchase_typetotal_reviews
(omitted — Steam's default)5,236,483
steam5,236,483
non_steam_purchase4,580,072
all9,816,519

So "all the reviews for CS2" is 53.3% of them unless you say otherwise, and nothing in the response says so. This actor defaults to all, and every summary also reports steamDefaultPurchaseTypeTotal so the gap is a number in your data rather than a footnote.

(The parts don't sum to the whole either: 5,236,483 + 4,580,072 = 9,816,555 against all's 9,816,519 — upstream's arithmetic disagrees with itself by 36.)

Other traps it handles

  • query_summary is complete on the first page only. Later pages return {num_reviews} and nothing else, so totals read off page 5 are null. Captured once, from page one, and kept.
  • An unknown filter value doesn't error — it silently answers a different question. filter=bogus returned the same cursor as filter=all, byte for byte; review_type=bogus returned all's totals; purchase_type=bogus fell back to steam. Every enum is validated here before the request goes out.
  • Filtering to positive or negative destroys the totals. review_type=positive|negative makes upstream stop reporting total_reviews, total_positive and total_negative entirely. The rows still come; the denominator doesn't. Reported as totalsUnavailableReason rather than printed as a zero.
  • An omitted language means English, not everything — 1,498,594 of CS2's 5,236,483. Defaults to all here. An unknown language honestly returns zero.
  • Off-topic ("review bombing") reviews are excluded by default, and on most games you can't tell: Cyberpunk 2077 measured 878,232 with the filter on against 884,470 with it off, while CS2, Valheim and Overwatch 2 were identical. Turn on reportOfftopicGap to get the hidden count as a number.
  • day_range is deliberately not offered. It filters the rows but leaves total_reviews at the unfiltered figure, so a run reads as "5.2M reviews in the last 30 days". The explicit dateFrom/dateTo window moves both.
  • HTTP 200 carries no information. Every outcome is a 200; the verdict is in the body's success field. success: 2 means Steam couldn't parse the request (App ID 0 or non-numeric). And a nonexistent App ID is indistinguishable from a real game with no reviews yet — both return success: 1 with total_reviews: 0.

Output

One dataset, recordType tells the rows apart:

  • SEARCH_SUMMARY — one per game: upstream's totals and score, pages fetched, short pages survived, stop reason, reachable fraction, what Steam's default would have said, and the off-topic gap.
  • REVIEW — one per review, with upstream's object passed through verbatim alongside normalised fields. Playtime is kept as two figures — playtimeAtReviewMinutes and playtimeForeverMinutes — because "how long had they played when they wrote this" and "how long have they played" are different questions, and collapsing them loses the only signal that says whether a review came after 2 hours or 2,000.
  • ERROR — one per input that failed, so every input maps to at least one row.

Every row carries the filter context it was produced under (purchaseTypeApplied, languageApplied, filterApplied, …) — without it a row isn't interpretable, since the same game yields a different corpus per setting.

Modes

  • reviews — walk the full stream for each game.
  • summary — one request per game for score and totals only. A cheap way to compare hundreds of games' ratings without pulling their reviews.

Anti-bot and limits

No WAF. Seven TLS profiles (chrome124, chrome131, chrome136, safari17_0, edge101, firefox133, chrome99_android) returned 200 cold with byte-identical 17,977-byte bodies. A proxy is optional and off by default.

num_per_page above 100 is silently clamped by Steam with no error, so it is capped in code. A 5,000-page backstop per game (~500k reviews) stops an uncapped run on a 9.8-million-review title from paging forever; it is reported as pageCapHit if reached.

Policy

store.steampowered.com/robots.txt places no restriction on /appreviews/ and names no AI crawler. Note that api.steampowered.com is Disallow: / — the Web API host is closed, which is worth knowing before anyone reaches for GetAppList to enumerate App IDs. This actor does not touch it.

Steam reviews are user-submitted content; check Valve's terms before redistributing them.