# Steam Game Reviews Scraper (`technicaldost/steam-game-reviews-scraper`) Actor

Collect public Steam game reviews with language, recommendation, date, playtime and Steam Deck filters. Official API, bounded pagination, no login or API key.

- **URL**: https://apify.com/technicaldost/steam-game-reviews-scraper.md
- **Developed by:** [Technical Dost Solutions](https://apify.com/technicaldost) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 successful 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

## Steam Game Reviews Scraper

Collect public reviews for Steam app IDs into an exportable dataset. Useful for game feedback research, competitor comparisons, patch-feedback checks and localization research.

This Actor uses Valve's current **IUserReviewsService/GetAppReviews/v1** API, not the deprecated Steam store `/appreviews` route. It requires no Steam login, browser, proxy purchase or API key. It collects source data, not AI sentiment or a complete history guarantee.

### Pricing

$0.50 per 1,000 successful reviews. $0.003 per run. Standard-run platform usage is included. Only successful eligible rows in the default dataset trigger the result charge. Error, not-found, skipped and robots-denied diagnostics do not trigger a result charge. The run fee, where listed, still applies to empty or failed runs. Memory is limited to 256–512 MB. Set a maximum run cost in Apify; inspect the actual dataset and run charge breakdown after an interruption. Input item limits bound work and do not replace the run spending limit.

### Quick start

Find an app ID in its Steam store address, such as `570` in `https://store.steampowered.com/app/570/`.

```json
{
  "appIds": [570],
  "maxReviewsPerApp": 100,
  "maxTotalReviews": 100,
  "languages": ["english"],
  "sort": "recent",
  "reviewType": "all",
  "purchaseType": "all"
}
```

Run the Actor, open **Review dataset**, then export JSON, CSV or Excel using Apify. Also inspect **Status and collection limits** for failures and stopping reasons. All exported counts refer to this run, not lifetime totals.

For negative feedback in a date window:

```json
{
  "appIds": [570, 730],
  "languages": ["all"],
  "sort": "recent",
  "reviewType": "negative",
  "dateFrom": "2026-10-01",
  "dateTo": "2026-10-31",
  "maxReviewsPerApp": 200,
  "maxTotalReviews": 400
}
```

Dates are UTC and include both boundary days. Both dates are required. They filter when a review was **created**, including when sorting by update time.

### Input reference

| Field | Default | Meaning and limit |
| --- | --- | --- |
| `appIds` | Required | 1–20 integer Steam app IDs; duplicates removed. URLs and numeric strings are not accepted. |
| `maxReviewsPerApp` | 100 | 1–1,000 saved reviews per app. |
| `maxTotalReviews` | 1,000 | 1–5,000 saved reviews across the whole run. Apps processed in input order. |
| `maxPagesPerApp` | 10 | 1–50 pages per app. Each page requests at most 100 reviews and never more than remaining output capacity. |
| `languages` | `["english"]` | 1–10 Steam API codes, e.g. english, german, french, schinese. `["all"]` requests every language. Unknown codes may yield no matches. |
| `sort` | `recent` | recent, updated, helpful or funny. Recent/updated are recommended for paging. |
| `reviewType` | `all` | all, positive or negative. The recommendation is Valve's thumbs-up/down, not inferred sentiment. |
| `purchaseType` | `all` | all, steam or non_steam. |
| `filterOfftopicActivity` | true | Whether Steam excludes activity it labels off-topic. |
| `dayRange` | 30 | Helpful sort only: 0–365 days. Zero is unrestricted. Steam can broaden the window when necessary. |
| `dateFrom`, `dateTo` | Unset | Paired YYYY-MM-DD creation-date boundaries. |
| `playtimeMinHours`, `playtimeMaxHours` | Unset | Whole hours at review time, between 0 and 1,000,000. Minimum cannot exceed maximum. |
| `primarilySteamDeck` | false | If true, only reviews from primarily Steam Deck players. False applies no Deck filter. |
| `includeAuthorIds` | false | Opt in to public author Steam IDs and author-based review links. |
| `requestDelayMillis` | 1,500 | 1,000–10,000 ms minimum spacing between requests. |

Unsupported fields cause validation failure before any network request. Publisher keys, cookies and arbitrary endpoints are intentionally unsupported.

### Output

The default dataset has one row for each distinct app ID and review ID found during this run. IDs remain strings to preserve 64-bit precision. Missing optional values are null; zero and false are retained.

Fields include:

- `appId`, `appUrl`, `reviewId`, `review`, `language`, `recommended`.
- `createdAt`, `updatedAt`, `timestampCreated`, `timestampUpdated`. ISO dates are UTC; timestamps are Unix seconds.
- `votesHelpful`, `votesFunny`, `weightedVoteScore`, `commentCount`.
- `steamPurchase`, `receivedForFree`, `writtenDuringEarlyAccess`, `primarilySteamDeck`, `refunded`.
- `developerResponse`, `developerRespondedAt` when provided by Steam.
- `playtimeForeverMinutes`, `playtimeLastTwoWeeksMinutes`, `playtimeAtReviewMinutes`, `deckPlaytimeAtReviewMinutes`, `authorPublicReviewCount`, `lastPlayedAt`.
- `authorSteamId` and `reviewUrl`, null by default and populated only when `includeAuthorIds` is enabled and Steam supplies an ID.
- `source` and `collectedAt` for provenance.

All playtime output fields use **minutes**, although input playtime filters use hours. Review text is original text and may include formatting, URLs or offensive language; escape it before displaying it in HTML.

#### Summary

The `SUMMARY` key-value record contains overall status, request-attempt count, applied filters, timestamps and per-app information:

- `reviewsCollected`, `pagesFetched`, `duplicatesSkipped`.
- `querySummary`: Steam's first-page summary, retained without reinterpretation. The aggregate score fields may be absent when filtering positive or negative reviews.
- `dayRangeUsed`: the effective Helpful window from Steam, if supplied.
- `totalMatching`: the matching total returned by Steam, if available. This is not a promise that the run collected all of them.
- `status`: success, partial, error or skipped.
- `stopReason`: empty_page, review_limit, global_limit, page_limit, repeated_cursor, missing_cursor, no_new_reviews, rate_limit or error.
- `error`: machine-readable error code and explanation when applicable.

A successful status means a request was processed, **not** that every review was downloaded. Check `stopReason` and counts. A run can succeed with an empty dataset if there are no matching public reviews. No app-name lookup or app-existence verification is performed, so an empty result alone does not prove an app ID exists.

Individual failed apps do not erase prior results. If some apps fail, the dataset is retained and summary status is partial. If every attempted app fails with no retained reviews, the run fails after saving the summary.

### Boundaries and reliability

- Only public reviews returned by Steam are collected. No login, private profile data, review comments, game descriptions, prices or hardware details are fetched.
- Anonymous API results can be cached for up to 10 minutes. This is not real-time monitoring.
- Steam controls rate limits and availability. Requests are serial. Transient network errors, HTTP 429 and 5xx have at most two retries. HTTP 4xx other than 429 are not retried. Retry-After is respected; delays longer than 60 seconds stop the app rather than retrying too early. Exhausted 429s stop remaining apps.
- Requests have a 25-second timeout and a 5 MiB response limit. Redirects are not followed. Requests are restricted to the official review endpoint.
- Bounded pagination ends at the first limit or stop condition. Helpful/funny ordering and a changing live dataset do not provide a complete-history guarantee. Rows are deduplicated within the current run only.
- Repeated scheduled runs can return the same reviews. Persistent incremental state, cursor resume, cross-run deduplication and change alerts are not provided.
- API payload changes, removal of reviews, outages or access restrictions can cause partial results. No bypass of blocks or authentication is attempted.
- You are responsible for your use of review data, applicable Steam terms and privacy requirements. This tool is not affiliated with Valve or Steam. Public availability does not grant unrestricted redistribution rights.

# Actor input Schema

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

One to twenty numeric IDs from Steam store URLs. Duplicate IDs are removed.

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

Maximum unique reviews saved per app.

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

Maximum reviews across all apps, processed in input order.

## `maxPagesPerApp` (type: `integer`):

Hard page limit per app.

## `dayRange` (type: `integer`):

Helpful sort only. Zero is unrestricted. Steam may widen the range.

## `requestDelayMillis` (type: `integer`):

Minimum delay between requests, including retries.

## `languages` (type: `array`):

Steam API language codes: english, german, schinese. Use \["all"] alone for every language.

## `sort` (type: `string`):

Recent and updated are recommended for pagination. Helpful and funny are bounded samples.

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

Steam thumbs-up/down filter, not AI sentiment.

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

All includes Steam and non-Steam purchases.

## `filterOfftopicActivity` (type: `boolean`):

Ask Steam to exclude activity it flags as off-topic.

## `includeAuthorIds` (type: `boolean`):

Opt in to public Steam IDs and author-based review permalinks. No profiles are fetched.

## `primarilySteamDeck` (type: `boolean`):

Only reviews where the author primarily used Steam Deck at review time.

## `dateFrom` (type: `string`):

Optional YYYY-MM-DD date. Both date fields required together. Applies to creation even with updated sorting.

## `dateTo` (type: `string`):

Optional YYYY-MM-DD date. Both date fields required together. Applies to creation even with updated sorting.

## `playtimeMinHours` (type: `integer`):

Optional whole-hour filter on playtime when reviewed.

## `playtimeMaxHours` (type: `integer`):

Optional whole-hour filter on playtime when reviewed.

## Actor input object example

```json
{
  "appIds": [
    570
  ],
  "maxReviewsPerApp": 100,
  "maxTotalReviews": 1000,
  "maxPagesPerApp": 10,
  "dayRange": 30,
  "requestDelayMillis": 1500,
  "languages": [
    "english"
  ],
  "sort": "recent",
  "reviewType": "all",
  "purchaseType": "all",
  "filterOfftopicActivity": true,
  "includeAuthorIds": false,
  "primarilySteamDeck": false
}
```

# Actor output Schema

## `reviews` (type: `string`):

One row per unique review per app in this run.

## `summary` (type: `string`):

Per-app counts, stop reasons, query summary, filters and errors. Inspect for partial results.

# 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": [
        570
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("technicaldost/steam-game-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": [570] }

# Run the Actor and wait for it to finish
run = client.actor("technicaldost/steam-game-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": [
    570
  ]
}' |
apify call technicaldost/steam-game-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,technicaldost/steam-game-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/BjI1odJ0LuUlbB0Tr/builds/3jJrVOvaRi9z0b1YD/openapi.json
