# Steam Reviews | $0.15/1K | Dates, Playtime & Resume (`apivault_labs/steam-reviews-source-probe`) Actor

Collect public Steam reviews using the current official API: date, language, rating, purchase and playtime filters, cursor checkpoints and bounded batch export. Private release candidate.

- **URL**: https://apify.com/apivault_labs/steam-reviews-source-probe.md
- **Developed by:** [Apivault Labs](https://apify.com/apivault_labs) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.12 / 1,000 useful steam reviews

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

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 Reviews Scraper РІР‚вЂќ Player Feedback, Playtime & Resume

![Steam Reviews illustration](https://raw.githubusercontent.com/apivault-labs/apivault-labs/9b01ab00464ccbefd9532b7e5b88007e0ca2a90c/assets/steam-reviews/cover-v1.png)

*Illustration only: decorative cards, stars and charts are not extracted fields or a screenshot of the output.*

Collect public Steam game reviews for player sentiment research, launch feedback analysis and comparisons between games. Export review text, positive/negative recommendations, dates, languages, helpfulness votes and available playtime. This is a **private commercial candidate**. Public release is pending owner review and the publication limit.

The collector uses the current official [Steam GetAppReviews API](https://partner.steamgames.com/doc/webapi/IUserReviewsService?language=english). No Steam key, login or proxy is configured. The retired store `/appreviews` endpoint is not used.

### Quick start

```json
{"appIds":[620],"maxReviews":1000,"pageSize":100,"languages":["english"]}
```

Use numeric Steam app IDs from store URLs: `620` is Portal 2 and `570` is Dota 2. Apps are processed in input order; the first app may consume the entire review allowance. Sorting is by newest **created** review. Updated-review sorting and game discovery are not implemented.

### Research scenarios

| Goal | Settings |
| --- | --- |
| Build a review dataset | One app, `maxReviews:1000` or more within bounds |
| Study negative feedback | `reviewType:"negative"`, optionally `languages:["all"]` |
| Study feedback within a release window | Both `createdFrom` and `createdUntil` |
| Analyze experienced players | `minPlaytimeHours:10`, optionally `maxPlaytimeHours:100` |
| Compare several games | Multiple `appIds`, a small `maxPagesPerApp`, enough total `maxReviews` |
| Continue a large export | Copy the previous run's complete `CONTINUATION` JSON as next input |

Five private Task scenarios were verified on candidate 0.2.1; each release candidate receives a separate regression check. They are not public Store entry points. No public Task quota is consumed.

### Date and playtime filters

```json
{
  "appIds":[620],
  "maxReviews":100,
  "createdFrom":"2026-10-01T00:00:00Z",
  "createdUntil":"2026-10-20T23:59:59Z",
  "minPlaytimeHours":10,
  "purchaseType":"steam"
}
```

Dates are inclusive and require a timezone and whole seconds. Supply **both** endpoints; one endpoint alone is rejected because Steam ignores a one-sided range. Playtime filters use whole **hours at the time the review was written**; exported playtime fields use **minutes**. Filters are sent to Steam and verified against returned fields. Unknown fields cannot satisfy a requested filter and are excluded. Source-filter mismatches are counted in `SUMMARY.filteredRows`.

`reviewType`: `all`, `positive`, `negative`. `purchaseType`: `all`, `steam`, `nonSteam`. Use official language codes such as `english`, `german`, `russian`, or `["all"]` for every language. Steam's default off-topic filtering is retained; this is not a promise to export every visible store review.

### Larger exports and continuation

Limits per run: 20 app IDs, 10,000 useful reviews, 100 reviews/request, 200 pages/app and 200 requests total. The default collection budget is 240 seconds. `maxRunSeconds` accepts 20РІР‚вЂњ600; set the Actor timeout at least 30 seconds higher. The time budget stops before starting another request so the actor can save its output. Source speed and rate limits can reduce the actual count.

After each saved page the key-value store contains:

- `CHECKPOINT`: opaque cursors, completion flags, query fingerprint and delivered review IDs.
- `CONTINUATION`: a complete input object you can copy into the next run.
- `SUMMARY` at normal completion: row/page/error counts, limits and stop reasons. A hard platform kill can leave only the last checkpoint.

Copy **CONTINUATION**, not SUMMARY, to continue. Games, their order and filters must remain the same; you can change page size, per-run limits and time budget. The checkpoint retains up to 100,000 delivered review IDs across the chain, with deduplication across normal resumed runs. At capacity the chain stops; it is not unlimited storage or a persistent monitor.

Writes use a page checkpoint **after** dataset output. If the process crashes between the dataset write and checkpoint write, replaying the last checkpoint can repeat that page. Deduplicate by `(appId, reviewId)` when joining exports after interrupted runs. Apify migrations/automatic restart continuation are not implemented. A checkpoint is user-editable, not a signed audit log. Steam cursors are live source cursors, not a consistent snapshot; availability and stable ordering are controlled by Steam.

### Dataset fields

| Fields | Meaning |
| --- | --- |
| `appId`, `reviewId` | Game and review IDs; review ID stays a string |
| `reviewText`, `language`, `recommended` | Original player feedback and source recommendation |
| `createdAt`, `updatedAt` | ISO UTC dates; unknown update date remains null |
| `helpfulVotes`, `funnyVotes`, `helpfulnessScore`, `commentCount` | Source votes, score and comment count |
| `playtimeMinutes`, `playtimeAtReviewMinutes`, `playtimeLastTwoWeeksMinutes` | Source playtime in minutes, with distinct time bases |
| `steamPurchase`, `receivedForFree`, `earlyAccess`, `primarilySteamDeck`, `refunded` | Source flags, null if unavailable |
| `source`, `reviewUrl` | Official endpoint and game review listing; reviewUrl is not an individual permalink |

Unknown values stay null. Actual zero and false are retained. Reviewer Steam IDs, names and profile links are omitted. Only reviews with a valid ID, nonblank text and valid creation timestamp enter the dataset; malformed records are counted separately.

### Results, exports and integration

Use the Output links for the dataset, summary and continuation. Apify dataset exports support JSON/CSV and other platform formats. Standard authenticated Apify Actor API runs and dataset endpoints can be used from Python, JavaScript or an n8n HTTP Request node. For this private candidate, the calling account needs access to the actor. No separate Steam-specific npm/n8n node, public GitHub client or Python package is claimed; dedicated integration packaging has not been completed.

### Costs and diagnostics

The owner-approved tariff is **$0.15 per 1,000 useful reviews on Free**, or **$0.12 per 1,000 on paid Apify plans**. There is **no Actor start fee**. Apify infrastructure usage is additional and paid by the user. One result event corresponds to one unique, valid review matching the requested filters and saved to the dataset; errors, malformed records, excluded reviews and detected duplicates are not review events. Infrastructure can still cost money when no reviews are found.

Set `maxTotalChargeUsd` in Apify run options to cap result-event charges. If the SDK accepts only part of a page, only those saved reviews enter the checkpoint. The current page cursor is retained so a resumed run can recover the unsaved reviews, with the already delivered IDs excluded. `PAYMENT_BUDGET` in SUMMARY is an incomplete run, not a full export. Result-event budget and `maxReviews` are separate bounds. QA evidence and resource costs are recorded separately.

Errors never become dataset rows. HTTP 429 stops remaining requests without retry or proxy rotation. Other source errors can produce partial output; all-source failure marks the run failed. A successful limited run does not imply all matching reviews were collected. `isComplete` is true only after every requested app reaches an empty source page, including completion flags from resumed runs.

Stop reasons include `MAX_REVIEWS`, `MAX_PAGES`, `RUN_BUDGET`, `CHECKPOINT_CAPACITY`, `NO_NEW_VALID_REVIEWS`, `MISSING_OR_REPEATED_CURSOR`, `SOURCE_ERROR`, `PAYMENT_BUDGET` and `SOURCE_EXHAUSTED`. A missing/repeated cursor retains a conservative checkpoint; resuming it may yield no new rows. Steam anonymous responses may be cached, and source rate limits can change. Do not repeatedly restart a 429 run unchanged.

### FAQ

**Does it collect thousands of reviews?** The candidate supports bounded batches up to 10,000 per run and continuation. Real counts depend on available matches, source speed and limits; a configured maximum is not proof of a completed export.

**Can I fetch only new reviews on a schedule?** Date windows can support bounded new runs, but automatic monitoring, durable scheduling and cross-window duplicate management are not part of this candidate.

**Is this a full Steam game scraper?** It collects public reviews for supplied app IDs. Game discovery, app details, sales/revenue estimates, profiles and market inventory are not implemented.

**Can I publish or buy it now?** This is private candidate preparation. Tariff verification, final owner review and public publication are tracked separately.

### Python and n8n integrations

Use the thin [Python client source](https://github.com/apivault-labs/apivault-labs/tree/main/packages/apivault-steam-reviews) and [PyPI package](https://pypi.org/project/apivault-steam-reviews/), or the [n8n community node](https://www.npmjs.com/package/n8n-nodes-apivault-steam-reviews) with its [source and manual example workflow](https://github.com/apivault-labs/apivault-labs/tree/main/community-nodes/n8n-nodes-apivault-steam-reviews).

```bash
pip install apivault-steam-reviews==0.1.0
```

```python
from apivault_steam_reviews import Client

result = Client().run(
    {"appIds": [620], "maxReviews": 10, "languages": ["english"]},
    max_total_charge_usd=0.02,
    max_rows=10,
)
print(result.summary)
print(result.rows)
```

Set your own `APIFY_TOKEN` environment variable. Both clients call this hosted Actor through the official Apify API and require your own account. Client packages have no subscription of their own; Actor result charges and platform usage apply. `max_rows` is only a download cap: also set `maxReviews` to limit collection. Start requests are not automatically retried. Read Existing Run in n8n or `Client().result(run_id)` downloads a saved run without starting a new paid run.

The n8n example is inactive and contains no credentials. Install `n8n-nodes-apivault-steam-reviews@0.1.0` on a self-hosted instance that permits community nodes. npm publication does not establish n8n verification or availability in n8n Cloud. Reading a run does not continue collection; copy its CONTINUATION input into a new run when needed. Each continuation run is separately billed.

# Actor input Schema

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

One to twenty numeric Steam app IDs, processed in order.

## `maxReviews` (type: `integer`):

Maximum useful reviews saved across all requested apps.

## `pageSize` (type: `integer`):

Maximum reviews requested in a single source page.

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

Maximum API pages per app; bounded runs may be incomplete.

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

Official Steam language codes such as english, or all.

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

Collect all, recommended, or not recommended reviews.

## `createdFrom` (type: `string`):

Inclusive ISO timestamp with timezone. Supply both date endpoints, for example 2026-01-01T00:00:00Z.

## `createdUntil` (type: `string`):

Inclusive ISO timestamp with timezone. Both endpoints are required.

## `minPlaytimeHours` (type: `integer`):

Filter author playtime when the review was written, in whole hours. Output playtime fields are in minutes.

## `maxPlaytimeHours` (type: `integer`):

Filter author playtime when the review was written, in whole hours. Output playtime fields are in minutes.

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

Include all reviews, only Steam purchases, or only non-Steam copies.

## `maxRunSeconds` (type: `integer`):

Stops collection before this time and saves continuation. Set Actor timeout at least 30 seconds higher.

## `resume` (type: `object`):

Paste the complete CHECKPOINT object from an earlier run with the same games and filters, or use the CONTINUATION record as the entire next input.

## Actor input object example

```json
{
  "appIds": [
    620
  ],
  "maxReviews": 200,
  "pageSize": 100,
  "maxPagesPerApp": 200,
  "languages": [
    "english"
  ],
  "reviewType": "all",
  "purchaseType": "all",
  "maxRunSeconds": 240
}
```

# Actor output Schema

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

No description

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

No description

## `checkpoint` (type: `string`):

No description

## `continuation` (type: `string`):

No description

# 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": [
        620
    ],
    "languages": [
        "english"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("apivault_labs/steam-reviews-source-probe").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": [620],
    "languages": ["english"],
}

# Run the Actor and wait for it to finish
run = client.actor("apivault_labs/steam-reviews-source-probe").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": [
    620
  ],
  "languages": [
    "english"
  ]
}' |
apify call apivault_labs/steam-reviews-source-probe --silent --output-dataset

```

## MCP server setup

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

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/ZqTL86UBGYnIPkwN5/builds/Ce2BsTzpMESibUcry/openapi.json
