L logiover
ecommerce · Jun 7, 2026 · 6 min read

Steam Reviews API Alternative: Bulk Export Game Reviews in 2026

How to bulk-export Steam game reviews using the semi-public appreviews endpoint plus cursor pagination — limits, quirks, and a clean output schema.

Steam sits on one of the richest review datasets in gaming, and getting it out is genuinely fiddly. There is a Steamworks endpoint that returns reviews as JSON, but it is per-app, cursor-paged, lightly documented, and full of edge cases that bite you somewhere around review number 5,000. This guide is an honest Steam reviews API alternative: what the semi-public surface actually gives you, where it lies to you, and how to bulk-export game reviews into a clean dataset in 2026.

The API gap, stated honestly

Steam does not publish a clean, supported “give me all reviews for this game” REST API in the way a modern SaaS would. What exists instead is the appreviews endpoint under the storefront/Steamworks surface:

https://store.steampowered.com/appreviews/<appid>?json=1

It is semi-public. It powers the review widgets on the store pages, so it is served to anonymous clients and needs no API key. But it was never marketed as a developer API, the parameter set is documented only in scattered community wikis, and Valve changes behavior without notice. Calling it a Steam reviews API alternative is fair as long as you go in knowing it is a storefront endpoint you are leaning on, not a contract Valve owes you.

The thing it absolutely does not do is span apps. Every call is scoped to a single appid. There is no “all reviews across the catalog” call. If you want a corpus, you iterate app IDs yourself.

What the endpoint gives you

For a given app, appreviews returns:

  • A query_summary block: total positive and negative counts, the overall review score, and the score description (“Very Positive”, “Mixed”, and so on).
  • A reviews array, each entry carrying the review text, the voted_up boolean (Steam reviews are thumbs up/down, not stars), helpful/funny vote counts, the timestamp created and updated, and a flag for whether the review was written during early access.
  • Author data: the SteamID, the author’s total games owned, their total reviews written, playtime forever, and crucially playtime_at_review — how many hours they had logged when they wrote it.
  • A cursor string for paging.

That playtime_at_review field is the reason serious analysts bother with Steam at all — you can weight a negative review by whether it came from someone with two hours or two hundred.

How the cursor pagination actually works

This is where a Steam reviews API alternative lives or dies. The endpoint pages with an opaque cursor:

  • First call uses cursor=*.
  • Each response returns a cursor value; you URL-encode it and pass it as the cursor for the next call.
  • You set num_per_page (max 100) and keep going until the returned batch is shorter than the page size — or until the cursor stops advancing.

The quirks you must code defensively for:

  • The cursor can repeat. Near the tail of large review sets, the endpoint sometimes hands back a cursor you have already seen. If you do not track seen cursors and break on a repeat, you loop forever. Always keep a set of visited cursors.
  • Forgetting to URL-encode the cursor silently returns the first page again. The cursor contains characters that must be encoded.
  • day_range only applies to certain filters. It is meaningful when filter=all is combined with the right sort, and ignored otherwise.
  • Key parameters shape the result set: filter (recent / updated / all), language (or all), review_type (positive / negative / all), purchase_type (steam / non_steam_purchase / all), and num_per_page.

A practical loop: filter=recent, language=all, purchase_type=all, num_per_page=100, advance the cursor, dedupe by recommendationid, and stop on a repeated cursor or an empty batch.

Rate limits and how to live with them

There is no published quota because, again, this is a storefront endpoint and not a sanctioned API. Treat it accordingly:

  • Keep request rate modest — a request every fraction of a second per app, not a flood. Valve will throttle a single IP that gets greedy.
  • For a multi-game corpus, rotate IPs and parallelize across apps rather than hammering one app’s cursor chain faster.
  • Expect occasional 429-style throttling and empty success responses; back off and retry rather than treating them as end-of-data.
  • A very popular title can have hundreds of thousands of reviews. Decide early whether you need the full history or just a recent window — pulling everything is an overnight job.

Try the Steam Game Reviews Scraper on Apify — feed it app IDs and get the full cursor-paged review history with playtime and author stats. No auth required.

A clean output schema

Normalize the nested response into flat, analysis-ready rows:

{
  "appid": 1086940,
  "game_name": "Example Game",
  "recommendation_id": "187654321",
  "voted_up": false,
  "review_text": "Great concept but it crashes on every boss fight.",
  "language": "english",
  "playtime_at_review_minutes": 412,
  "playtime_forever_minutes": 980,
  "author_steamid": "7656119800000000",
  "author_num_reviews": 23,
  "author_games_owned": 184,
  "votes_helpful": 47,
  "votes_funny": 3,
  "steam_purchase": true,
  "received_for_free": false,
  "written_during_early_access": false,
  "timestamp_created": "2026-04-18T20:11:00Z",
  "timestamp_updated": "2026-04-19T08:02:00Z",
  "review_score_desc": "Mostly Positive",
  "total_positive": 8421,
  "total_negative": 1320,
  "scraped_at": "2026-06-07T12:00:00Z"
}

Convert Steam’s epoch timestamps to ISO, keep playtime in minutes (the API’s native unit), and carry the app-level query_summary counts onto each row so any single export is self-describing.

Use cases

  • Sentiment and patch-impact tracking. Watch the positive/negative ratio move after an update; correlate complaint spikes with release dates.
  • Refund and quality signals. Reviews written under two hours of playtime (Steam’s refund window) behave differently — segment on playtime_at_review.
  • Localization priorities. The language field tells you where a game’s player base actually is.
  • ML training data. Thumbs-up/down labels plus rich text make a clean binary-sentiment corpus.

Build it yourself vs. a managed actor

Building it is a weekend project and then a maintenance tax. The cursor dedupe, the encoding trap, the throttling back-off, and converting app-level data into flat rows are all small jobs that add up — and Valve quietly changes endpoint behavior a couple of times a year. A managed actor turns all of that into a list of app IDs and a filter. For a one-off pull of one game, roll your own. For a monitoring pipeline across a catalog, the managed route is the one that survives Valve’s next tweak.

Common pitfalls

  • Infinite loops from repeated cursors — the single most common bug. Track visited cursors and break.
  • Treating empty batches as the end when they are actually throttling — distinguish a real end-of-data from a back-off signal.
  • Star-rating assumptions — Steam has no stars, only voted_up. Do not invent a 1–5 scale.
  • Ignoring received_for_free and steam_purchase — free keys and non-Steam purchases skew sentiment; keep the flags so you can filter.

Wrapping up

A real Steam reviews API alternative has to be honest: the appreviews endpoint is semi-public, per-app, cursor-paged, and occasionally hostile, but it is the surface that genuinely lets you bulk-export game reviews with playtime-weighted author data. Code the cursor dedupe carefully, throttle politely, and flatten the response into clean rows. Build it yourself for a single title, or let a managed scraper absorb the pagination quirks for a catalog-wide pipeline.

Open the Steam Game Reviews Scraper on Apify — cursor pagination, playtime weighting, and clean rows handled for you. Pay per review exported, no key needed.

Related guides