# Steam Reviews Scraper · Game Reviews, Ratings & Playtime (`reapx/steam-reviews-scraper`) Actor

Scrape Steam game reviews, ratings, playtime, helpfulness votes, and purchase types across any Steam App ID. Fast HTTP scraper, no login required.

- **URL**: https://apify.com/reapx/steam-reviews-scraper.md
- **Developed by:** [Tarek Etman](https://apify.com/reapx) (community)
- **Categories:** Games, Marketing, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.30 / 1,000 steam game review returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

![reapX — public sources in, addressable records out](https://reapx.dev/reapx.gif)

## Steam Reviews Scraper · Game Reviews, Ratings & Playtime

Extract user reviews, star ratings, playtime hours, helpfulness votes, and purchase verification metrics from any game on Steam. The **Steam Reviews Scraper** provides structured data from Steam's official review feeds without requiring user login or Steam API credentials.

> Maintained by **reapX**. Every row cites the Apify run that produced it — nothing is
> inferred, modelled or filled in, and a field absent from the source is absent from the row.
> The extracted archive for this source is browsable at
> [reapx.dev/data/steam-reviews-scraper/](https://reapx.dev/data/steam-reviews-scraper/) and mirrored as an open dataset on
> [Hugging Face](https://huggingface.co/datasets/reapxdev/steam-reviews-scraper) and
> [Kaggle](https://www.kaggle.com/datasets/reapxdev/steam-reviews-scraper). Questions: reapxdev@proton.me

Maintained by reapX. Public source citation guarantee: Steam App Reviews API.

***

### Features

- 🎮 **Any Steam App ID or Store URL**: Extract reviews for any game, application, or software listed on Steam.
- ⏱️ **Detailed Playtime Metrics**: Capture total hours played (`playtimeForeverHours`), hours played at time of review (`playtimeAtReviewHours`), and recent 2-week playtime (`playtimeLastTwoWeeksHours`).
- 👍 **Helpfulness & Sentiment Scoring**: Include `weightedVoteScore`, `votesUp` (helpful), `votesFunny`, and recommendation status (`votedUp`).
- 🛒 **Purchase & Platform Verification**: Track whether the game was purchased directly on Steam (`steamPurchase`), received for free (`receivedForFree`), or played primarily on Steam Deck (`primarilySteamDeck`).
- 🌐 **Global Language Filtering**: Fetch reviews in English, Simplified Chinese, German, Spanish, French, Japanese, or all supported Steam languages.
- ⚡ **Fast & Lightweight HTTP Scraper**: Built using direct async HTTP requests without expensive headless browsers.

***

### ⬇️ Input

The actor accepts a JSON input configuration specifying target Steam App IDs, review limits, language, purchase method, and sorting options.

#### Input Parameters

| Field | Type | Default | Description |
|---|---|---|---|
| `appIds` | Array | `["1086940", "570", "730"]` | Array of Steam App IDs or Store URLs to scrape reviews for (e.g. Baldur's Gate 3, Dota 2, CS2). |
| `maxReviewsPerApp` | Integer | `100` | Maximum number of reviews to extract per game (1 to 10,000). |
| `maxTotalReviews` | Integer | `500` | Global cap on total review items collected across all processed App IDs. |
| `reviewType` | String | `"all"` | Filter by recommendation outcome: `"all"`, `"positive"` (recommended), or `"negative"`. |
| `filter` | String | `"all"` | Review sorting mode: `"all"` (most helpful / weighted), `"recent"`, or `"updated"`. |
| `language` | String | `"all"` | Language code for reviews (e.g. `"english"`, `"spanish"`, `"german"`, or `"all"`). |
| `purchaseType` | String | `"all"` | Filter by purchase type: `"all"`, `"steam"` (direct store purchase), or `"non_steam_purchase"`. |

#### Example Input JSON

```json
{
  "appIds": [
    "1086940",
    "1245620",
    "292030"
  ],
  "maxReviewsPerApp": 100,
  "maxTotalReviews": 300,
  "reviewType": "positive",
  "filter": "all",
  "language": "english",
  "purchaseType": "steam"
}
```

***

### ⬆️ Output

Scraped items are pushed directly to the run's default dataset. Each row represents a single user review aggregated under its game's primary `appId`.

#### Output Fields Reference

| Field | Type | Example | Description |
|---|---|---|---|
| `appId` | String | `"1086940"` | Unique Steam App ID for the game. Primary identifier. |
| `appName` | String | `"Baldur's Gate 3"` | Canonical game title. |
| `reviewId` | String | `"230513815"` | Unique Steam recommendation / review ID. |
| `authorSteamId` | String | `"76561199067288820"` | 64-bit Steam ID of the reviewer. |
| `authorPersonaName` | String | `"Gamer123"` | Steam display name / persona of author. |
| `authorProfileUrl` | String | `"https://steamcommunity.com/id/gamer123/"` | Direct link to author's Steam profile. |
| `authorGamesOwned` | Integer | `184` | Total Steam games owned by author. |
| `authorNumReviews` | Integer | `39` | Total reviews written by author across Steam. |
| `playtimeForeverHours` | Number | `123.5` | Total hours played in this game. |
| `playtimeAtReviewHours` | Number | `89.8` | Hours played at the moment review was posted. |
| `playtimeLastTwoWeeksHours` | Number | `10.2` | Hours played in past fortnight. |
| `language` | String | `"english"` | ISO / Steam language code. |
| `reviewText` | String | `"Outstanding RPG with impressive world building..."` | Full text of user review. |
| `timestampCreated` | String | `"2026-08-01T12:00:00Z"` | ISO 8601 creation timestamp. |
| `timestampUpdated` | String | `"2026-08-01T12:00:00Z"` | ISO 8601 last updated timestamp. |
| `votedUp` | Boolean | `true` | `true` for positive (thumbs up), `false` for negative. |
| `votesUp` | Integer | `42` | Count of community helpfulness votes. |
| `votesFunny` | Integer | `5` | Count of funny votes. |
| `weightedVoteScore` | Number | `0.85` | Steam helpfulness score algorithm (0.0 - 1.0). |
| `commentCount` | Integer | `3` | Number of comments on this review. |
| `steamPurchase` | Boolean | `true` | `true` if bought directly via Steam Store. |
| `receivedForFree` | Boolean | `false` | `true` if reviewer received product for free. |
| `writtenDuringEarlyAccess` | Boolean | `false` | `true` if written during Early Access period. |
| `primarilySteamDeck` | Boolean | `false` | `true` if played primarily on Steam Deck. |

#### Sample Output Record

```json
{
  "appId": "1086940",
  "appName": "Baldur's Gate 3",
  "reviewId": "230513815",
  "authorSteamId": "76561199067288820",
  "authorPersonaName": "whenizzywasthere~",
  "authorProfileUrl": "https://steamcommunity.com/profiles/76561199067288820",
  "authorGamesOwned": 184,
  "authorNumReviews": 39,
  "playtimeForeverHours": 123.5,
  "playtimeAtReviewHours": 89.8,
  "playtimeLastTwoWeeksHours": 10.2,
  "language": "english",
  "reviewText": "An incredible RPG experience that sets new standards for choice and storytelling.",
  "timestampCreated": "2026-08-01T12:00:00Z",
  "timestampUpdated": "2026-08-01T12:00:00Z",
  "votedUp": true,
  "votesUp": 625,
  "votesFunny": 1286,
  "weightedVoteScore": 0.9135,
  "commentCount": 0,
  "steamPurchase": true,
  "receivedForFree": false,
  "writtenDuringEarlyAccess": false,
  "primarilySteamDeck": false
}
```

***

### How it works

1. **Input Parsing & Validation**: The scraper cleans provided Steam App IDs or URLs and deduplicates input parameters.
2. **App Title Resolution**: Resolves canonical game names via official Steam Store endpoints or internal high-speed cache.
3. **Cursor-Based Feed Pagination**: Streams review pages sequentially using Steam's cursor token system for complete dataset extraction.
4. **Data Normalization**: Converts raw Steam timestamps, playtime minutes, and review metadata into clean, standardized ISO schemas.
5. **Streaming Output**: Emits datasets per event row in real-time to ensure zero data loss during long-running tasks.

***

### ❓ FAQ

##### Where do I find a game's Steam App ID?

Look at the URL of any game's page on the Steam Store: `https://store.steampowered.com/app/1086940/Baldurs_Gate_3/`. The number `1086940` is the App ID. You can also paste the full URL directly into `appIds`.

##### How many reviews can I scrape?

You can set `maxReviewsPerApp` up to 10,000 per game. For large batch jobs covering dozens of games, set `maxTotalReviews` to match your budget cap.

##### Do I need a Steam account or API key?

No. The scraper accesses public Steam review feeds and requires no login or API keys.

##### Can I filter by Steam Deck reviews?

Yes! Each output record contains the `primarilySteamDeck` boolean field indicating whether the reviewer logged most of their playtime on a Steam Deck handheld.

***

### 💬 Your feedback

Have suggestions, feature requests, or custom scraping requirements? We actively maintain this scraper. Reach out via email or open an issue on the repository.

***

*Disclaimer: Unofficial - not affiliated with Valve or Steam. Collects public data only. reapx. Contact reapxdev@proton.me.*

### 🧪 Example input

A real, runnable configuration — this is an actual input this Actor has run with.

```json
{
  "appIds": [
    "1086940",
    "1245620",
    "292030",
    "1091500",
    "489830",
    "377160",
    "582010"
  ],
  "maxReviewsPerApp": 50,
  "maxTotalReviews": 350
}
```

### 📄 Sample output

One real row from a real run of this Actor, unedited.

```json
{
  "appId": "1086940",
  "appName": "Baldur's Gate 3",
  "reviewId": "229459391",
  "authorSteamId": "76561199572529646",
  "authorPersonaName": "aadr1",
  "authorProfileUrl": "https://steamcommunity.com/profiles/76561199572529646/",
  "authorGamesOwned": 0,
  "authorNumReviews": 1,
  "playtimeForeverHours": 1138.6,
  "playtimeAtReviewHours": 1118.0,
  "playtimeLastTwoWeeksHours": 3.4,
  "language": "english",
  "reviewText": "Just left character creation. Excited to see what the game has in store!",
  "timestampCreated": "2026-07-03T00:04:11Z",
  "timestampUpdated": "2026-07-03T00:04:11Z",
  "votedUp": true,
  "votesUp": 625,
  "votesFunny": 1287,
  "weightedVoteScore": 0.9135,
  "commentCount": 0,
  "steamPurchase": true,
  "receivedForFree": false,
  "writtenDuringEarlyAccess": false,
  "primarilySteamDeck": false
}
```

### ⚠️ Run outcomes and error handling

This Actor reports what happened in the run's **status message**, and it always keeps whatever it collected. These are the outcomes you can get and what each one means.

| Outcome | What it means |
|---|---|
| **Success** | Rows were returned and you were charged `steam-review` at $0.002 per row. |
| **No matches** | The source returned nothing for your filters. **Nothing is charged.** Widen the date window or drop a filter. |

#### What is guaranteed either way

- **Every row is pushed as it is built**, not buffered to the end of the run. Anything that buffers output loses everything to a timeout, a block or a migration; this does not.
- **A field absent from the source is absent from the row.** Nothing is inferred, modelled or filled in to make a row look complete.

# Actor input Schema

## `appIds` (type: `array`):

Array of Steam App IDs or Store URLs to scrape reviews for (e.g., <code>\["1086940", "570", "730"]</code> for Baldur's Gate 3, Dota 2, CS2).<br><br><b>Consequence:</b> Specifying more games increases execution duration and billing events linearly. Leaving this list empty defaults to scraping top featured games.

## `maxReviewsPerApp` (type: `integer`):

Maximum number of reviews to extract per Steam App ID.<br><br><b>Consequence:</b> Higher caps allow deep review sentiment analysis but increase run duration and event costs proportionately. Default is <code>100</code> reviews per game.<br><br>The higher the number, the longer the run takes and the more you are charged, because you pay per row returned.

## `maxTotalReviews` (type: `integer`):

Global cap on total review items collected across all processed App IDs.<br><br><b>Consequence:</b> Acts as a safety limit for cost control. The actor stops immediately upon reaching this cap regardless of remaining App IDs. Default is <code>500</code>.<br><br>The higher the number, the longer the run takes and the more you are charged, because you pay per row returned.

## `reviewType` (type: `string`):

Filter reviews by user recommendation outcome.<br><br><b>Options:</b> <code>all</code> (positive & negative), <code>positive</code> (thumbs up only), or <code>negative</code> (thumbs down only). Default is <code>all</code>.

## `filter` (type: `string`):

Sorting criteria for retrieved review feeds.<br><br><b>Options:</b> <code>all</code> (most helpful / weighted), <code>recent</code> (newest first), or <code>updated</code> (recently updated reviews). Default is <code>all</code>.

## `language` (type: `string`):

Language of reviews to fetch (e.g. <code>english</code>, <code>spanish</code>, <code>german</code>, <code>schinese</code>, or <code>all</code> for all languages).<br><br><b>Consequence:</b> Specifying <code>all</code> fetches reviews in every supported Steam language. Default is <code>all</code>.<br><br>Leave this field empty to skip this filter.

## `purchaseType` (type: `string`):

Filter by Steam purchase status.<br><br><b>Options:</b> <code>all</code> (purchased on Steam & key activations), <code>steam</code> (direct Steam Store purchase), or <code>non\_steam\_purchase</code> (key/gift redemptions). Default is <code>all</code>.

## Actor input object example

```json
{
  "appIds": [
    "1086940",
    "570",
    "730"
  ],
  "maxReviewsPerApp": 100,
  "maxTotalReviews": 500,
  "reviewType": "all",
  "filter": "all",
  "language": "all",
  "purchaseType": "all"
}
```

# Actor output Schema

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

Every user review extracted from Steam, one row per item, in the default dataset.

# 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 = {
    "appIds": [
        "1086940",
        "570",
        "730"
    ],
    "maxReviewsPerApp": 100,
    "maxTotalReviews": 500
};

// Run the Actor and wait for it to finish
const run = await client.actor("reapx/steam-reviews-scraper").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 = {
    "appIds": [
        "1086940",
        "570",
        "730",
    ],
    "maxReviewsPerApp": 100,
    "maxTotalReviews": 500,
}

# Run the Actor and wait for it to finish
run = client.actor("reapx/steam-reviews-scraper").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 '{
  "appIds": [
    "1086940",
    "570",
    "730"
  ],
  "maxReviewsPerApp": 100,
  "maxTotalReviews": 500
}' |
apify call reapx/steam-reviews-scraper --silent --output-dataset

```

## MCP server setup

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

```

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/11eazhdZ1RO5TZ4dj/builds/bY6J9wWvyVftIuGaC/openapi.json
