# Steam Reviews Scraper (`superslowsloth/steam-reviews-scraper`) Actor

Scrape Steam reviews and store details for any game. Reviews carry the text, thumbs up or down, helpfulness votes, both playtime figures and the language. Game records carry name, release date, developers, publishers, genres, platforms, price with currency and Metacritic score.

- **URL**: https://apify.com/superslowsloth/steam-reviews-scraper.md
- **Developed by:** [Superslow Sloth](https://apify.com/superslowsloth) (community)
- **Categories:** Games, E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.40 / 1,000 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?

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

## Steam Reviews and Game Details Scraper

Collects user reviews and store listings from Steam for any app, in one run.
For each app you ask for, the actor optionally emits the game's store details
first and then walks its reviews, so a single dataset carries both what a game
is and what players say about it.

No Steam account, API key or login is needed. Both endpoints this actor reads
are public.

### What you get

Every record carries a `type` field, which is either `game` or `review`.

#### `type: "review"`

| Field | Meaning |
|---|---|
| `recommendation_id` | Steam's own ID for the review. Unique, and what de-duplication is keyed on. |
| `app_id` | The app the review is about. |
| `review` | The review text. |
| `voted_up` | `true` for Recommended, `false` for Not Recommended. |
| `language` | Steam language code, e.g. `english`, `schinese`. |
| `votes_up`, `votes_funny` | Helpful and funny vote counts. |
| `weighted_vote_score` | Steam's helpfulness score, 0-1. Always a number here; Steam itself sends it as a string on some reviews and a float on others. |
| `comment_count` | Comments on the review. |
| `timestamp_created`, `timestamp_updated` | Unix seconds. |
| `steam_purchase` | `true` if bought on Steam, `false` if a key was activated elsewhere. |
| `received_for_free`, `refunded`, `written_during_early_access`, `primarily_steam_deck` | Steam's own flags. |
| `author_steamid` | The reviewer's 64-bit SteamID. |
| `author_playtime_at_review_minutes` | Playtime **in minutes** when the review was written. |
| `author_playtime_forever_minutes`, `author_playtime_last_two_weeks_minutes` | Playtime in minutes. |
| `author_num_games_owned`, `author_num_reviews`, `author_last_played` | Reviewer profile figures. |

#### `type: "game"`

| Field | Meaning |
|---|---|
| `app_id`, `name` | Identity. |
| `app_type` | `game`, `dlc`, `demo`, `music`, `video`, `hardware` or `mod`. |
| `is_free` | Free-to-play flag. |
| `release_date`, `coming_soon` | Release date as Steam formats it, and whether it is still unreleased. |
| `developers`, `publishers` | Lists of names. |
| `genres`, `categories` | Lists of labels, e.g. `Action`, `Multi-player`. |
| `platforms` | Any of `windows`, `mac`, `linux`. |
| `price_final`, `price_initial` | Price in the **smallest currency unit** - `3999` means $39.99. |
| `price_currency` | ISO code the price is quoted in. See the note on `countryCode` below. |
| `price_discount_percent`, `price_formatted` | Current discount, and the price as Steam displays it. |
| `metacritic_score`, `metacritic_url` | Metacritic rating, when the app has one. |
| `recommendations_total` | Steam's total review count for the app. |
| `required_age`, `short_description`, `website`, `header_image`, `supported_languages` | Store listing extras. |

### Fields that can be missing, and why they are `null` and not `0`

Steam does not report these for every app. Where it does not, the field is
`null`. A `0` would read as a measurement - "this game costs nothing", "this
game scored zero on Metacritic" - and those are different claims from "Steam
did not say".

- **`price_*` is `null` for free-to-play games** (Steam sends no price block at
  all), for unreleased games, and for games not sold in the country you asked
  for.
- **`metacritic_score` and `metacritic_url` are `null` for most apps.** Only a
  minority have a Metacritic entry.
- **`recommendations_total` is `null`** for apps with too few reviews for Steam
  to publish a total.
- **`website`, `required_age` and the playtime fields** are absent on some
  records and stay `null`.

### Pricing currency depends on where the request comes from

Steam's details endpoint quotes prices in the currency of whichever address the
request leaves from. With a rotating residential proxy that means the same game
can come back in USD on one run and MXN on the next. The `countryCode` input
pins it - it defaults to `US`, and `price_currency` always states what was
actually returned.

### Looking games up by name

Set `searchTerms` and the actor resolves each name to an app ID through Steam's
own store search - the same endpoint the store's search box calls, which needs
no credentials. It is a **fuzzy relevance search, not an exact lookup**: it
takes the top-ranked match, so searching `witcher 3` can land on the base game
or on a DLC depending on how Steam ranks them that day. An exact `appIds` entry
is always the more precise input, and names that resolve to nothing are logged
and skipped rather than guessed at.

### Filters

`language`, `reviewType` and `purchaseType` were each verified against the live
endpoint to actually change the result rather than being silently ignored. One
caveat on `purchaseType`: free-to-play titles have no product-key activations,
so every review is a Steam purchase and the filter appears to do nothing there.
It works normally on paid games.

Reviews are read in `recent` order rather than Steam's default relevance
ordering, because relevance is not a stable sort between requests and paging
through it revisits some reviews while skipping others.

### Cost and de-duplication

You are charged once per record actually delivered to the dataset: one
`item-scraped` per game and one `review-scraped` per review, both after the
record is pushed. Reviews are de-duplicated on `recommendation_id` before
charging, so a review Steam serves on two pages is billed once.

A run that legitimately finds nothing - an app with no reviews matching your
filters - pushes nothing and charges nothing beyond the actor start fee.

# Actor input Schema

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

One or more Steam app IDs. A full store URL such as https://store.steampowered.com/app/570/Dota\_2/ works too - the ID is read out of it. Game names are not accepted here; set searchTerms instead.

## `searchTerms` (type: `array`):

Optional. Game names resolved to app IDs through Steam's own store search, then scraped alongside appIds. Search is fuzzy and takes the top-ranked match, so an exact app ID is always more precise.

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

How many reviews to collect for each app. Steam serves 100 per page and further pages are fetched automatically. Set 0 to collect game details only.

## `includeGameDetails` (type: `boolean`):

Emit one record per app with its store listing - name, type, release date, developers, publishers, genres, price, Metacritic score and platforms - before that app's reviews.

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

Steam language code such as english, schinese, russian or brazilian. Use all for every language. Verified to filter the results rather than being ignored.

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

Restrict to recommended (positive) or not recommended (negative) reviews, or take both.

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

Restrict to reviews from people who bought the game on Steam, or to those who activated a product key elsewhere. Free-to-play titles have no key activations, so this makes no difference there.

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

Optional. Limits reviews to those written within this many days, up to Steam's own maximum of 365. Leave empty for no time limit.

## `countryCode` (type: `string`):

Two-letter country code deciding which currency prices are quoted in. Without it Steam prices in the currency of whichever address the request leaves from, so the same game returns a different currency between runs.

## `proxyConfiguration` (type: `object`):

Recommended. Steam rate-limits repeated requests from one address and answers with a block page rather than an error code.

## Actor input object example

```json
{
  "appIds": [
    "570"
  ],
  "maxReviews": 100,
  "includeGameDetails": true,
  "language": "all",
  "reviewType": "all",
  "purchaseType": "all",
  "countryCode": "US",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `reviews` (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": [
        "570"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("superslowsloth/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": ["570"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,superslowsloth/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/ObVPYGytBBgKFUKhW/builds/07J27SDxVO5fuOGuu/openapi.json
