# Steam Reviews Scraper — Game Reviews, Prices & Tags (`tortuga/steam-scraper`) Actor

Scrape Steam games and user reviews: search results, app details (price, discounts, tags, genres, release date, developer, platforms) and reviews with votes, playtime and language.

- **URL**: https://apify.com/tortuga/steam-scraper.md
- **Developed by:** [Trevor Ortega](https://apify.com/tortuga) (community)
- **Categories:** E-commerce, Other
- **Features:** 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 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 Store & Reviews Scraper

Scrape Steam games and user reviews: search results, app details (price, discounts, tags, genres, release date, developer, platforms) and reviews with votes, playtime and language.

Steam Store & Reviews Scraper reads the public JSON endpoints behind `store.steampowered.com` and turns them into a clean dataset. Three modes cover the whole funnel: **search** a keyword and get every result with price, discount and review score; pull **details** for any app ID (price in your region, user tags, genres, categories, release date, developers, Metacritic, achievements, DLC); or collect **reviews** with helpful/funny votes, playtime, purchase type and language, plus a per-app review summary (total positive/negative, "Very Positive"). No Steam account or API key is needed and mature (age-gated) games work. Download JSON, CSV or Excel, or use the API from Python, Node, n8n or Google Sheets. You pay only for the items you get.

### What data does Steam Store & Reviews Scraper extract?

Every item has a `type` field: `review`, `summary`, `app` or `search`.

#### Review items (`type: "review"`, mode `reviews`)

| Field | Description |
|---|---|
| `appId`, `appName` | Steam app ID and name |
| `recommendationId` | Steam's review ID |
| `url` | Public review page on steamcommunity.com |
| `language` | Steam language code (`english`, `schinese`, `russian`, ...) |
| `text` | Review text |
| `votedUp` | `true` = Recommended, `false` = Not recommended |
| `votesUp`, `votesFunny`, `commentCount` | Helpful votes, funny votes and comments |
| `weightedVoteScore` | Steam's helpfulness score (0-1) |
| `steamPurchase`, `receivedForFree`, `writtenDuringEarlyAccess`, `refunded`, `primarilySteamDeck` | Purchase and context flags |
| `createdAt`, `updatedAt` | ISO 8601 UTC timestamps |
| `playtimeForeverMinutes`, `playtimeAtReviewMinutes`, `playtimeLastTwoWeeksMinutes`, `lastPlayedAt` | Reviewer playtime in this game |
| `numGamesOwned`, `numReviews` | Reviewer's public library size and review count |
| `authorSteamId` | Public numeric Steam ID printed on every review (no profile is fetched) |
| `authorName` | Reviewer's Steam display (persona) name as shown on the review |
| `authorUsername` | Reviewer's custom profile URL handle (`steamcommunity.com/id/<handle>/`) when they set one, otherwise `null` |
| `authorUrl` | Reviewer's public Steam Community profile URL |
| `authorId` | Reviewer's SteamID64 as a string (same value as `authorSteamId`) |
| `reactions` | `[{type, count}]` award reactions on the review |

#### Review summary items (`type: "summary"`, one per app in mode `reviews`)

`appId`, `appName`, `url`, `reviewScore` (0-9), `reviewScoreDesc` (`Very Positive`), `totalPositive`, `totalNegative`, `totalReviews`, `positivePercent`. The totals respect your language/type/purchase filters.

#### App items (`type: "app"`, mode `details`)

| Field | Description |
|---|---|
| `appId`, `name`, `url`, `appType` | Identity; `appType` is `game`, `dlc`, `demo`, `music`, ... |
| `isFree`, `price`, `originalPrice`, `currency`, `discountPercent`, `priceFormatted` | Price in the region given by **Country code** (`price` is a number, e.g. `59.99`) |
| `releaseDate`, `comingSoon` | Release date text as shown on the store and the coming-soon flag |
| `developers`, `publishers` | Lists of names |
| `genres`, `categories` | Store genres (`Action`) and categories (`Multi-player`, `Steam Achievements`) |
| `tags`, `tagsDetailed` | Top 20 user tags in Steam's order; `tagsDetailed` adds `id` and `count` |
| `platforms` | Subset of `windows`, `mac`, `linux` |
| `metacriticScore`, `metacriticUrl`, `recommendationsTotal` | Critic score and total Steam recommendations |
| `headerImage`, `capsuleImage`, `screenshots`, `movies` | Media URLs (trailers as HLS/DASH streams) |
| `shortDescription`, `aboutTheGame`, `website` | Plain-text descriptions |
| `supportedLanguages`, `fullAudioLanguages` | Interface languages and those with full audio |
| `achievementsCount`, `dlcCount`, `dlcAppIds`, `packages` | Achievements, DLC and purchasable package IDs |
| `requiredAge`, `contentDescriptors`, `controllerSupport` | Age rating, mature-content notes and controller support |

#### Search items (`type: "search"`, mode `search`)

`searchTerm`, `appId` (or `packageId`/`bundleId` for bundles), `name`, `url`, `price`, `originalPrice`, `currency`, `priceFormatted`, `isFree`, `discountPercent`, `releaseDate`, `reviewSummary` (`Overwhelmingly Positive`), `reviewPositivePercent`, `reviewCount`, `platforms`, `thumbnail`, `tagIds`.

### How to use Steam Store & Reviews Scraper

1. Pick a **Mode**: `reviews`, `details` or `search`.
2. For `reviews` and `details`, paste **App IDs** or store URLs (`570`, `https://store.steampowered.com/app/730/Counter-Strike_2/`), one per line. For `search`, enter **Search terms**.
3. Set **Max items** (and optionally **Max reviews per app**) to cap the run and the cost.
4. Optionally filter reviews by **Review language**, **Review type** (positive/negative) and **Purchase type**, or set **Country code** for prices.
5. Click **Start**. Results appear in the **Dataset** tab; export from there or use the API.

### Input example

```json
{
  "mode": "reviews",
  "appIds": ["570", "https://store.steampowered.com/app/730/Counter-Strike_2/"],
  "maxItems": 2000,
  "maxReviewsPerApp": 1000,
  "reviewsFilter": "recent",
  "reviewLanguage": "english",
  "reviewType": "all",
  "purchaseType": "all"
}
```

```json
{ "mode": "details", "appIds": ["1091500", "367520"], "countryCode": "de" }
```

```json
{ "mode": "search", "searchTerms": ["hollow knight", "roguelike deckbuilder"], "maxItems": 200 }
```

### Output example

```json
{
  "type": "review",
  "appId": 570,
  "appName": "Dota 2",
  "recommendationId": "234729359",
  "url": "https://steamcommunity.com/profiles/76561199800017251/recommended/570/",
  "language": "english",
  "text": "Still the deepest MOBA there is. 2000 hours and counting.",
  "votedUp": true,
  "votesUp": 12,
  "votesFunny": 1,
  "weightedVoteScore": 0.61,
  "commentCount": 0,
  "steamPurchase": true,
  "receivedForFree": false,
  "writtenDuringEarlyAccess": false,
  "refunded": false,
  "primarilySteamDeck": false,
  "createdAt": "2026-09-07T21:16:37Z",
  "updatedAt": "2026-09-07T21:16:37Z",
  "playtimeForeverMinutes": 121955,
  "playtimeAtReviewMinutes": 121952,
  "playtimeLastTwoWeeksMinutes": 88,
  "lastPlayedAt": "2026-09-07T21:19:12Z",
  "numGamesOwned": 41,
  "numReviews": 3,
  "authorSteamId": "76561199800017251",
  "authorName": "_kinix",
  "authorUsername": null,
  "authorUrl": "https://steamcommunity.com/profiles/76561199800017251/",
  "authorId": "76561199800017251",
  "reactions": []
}
```

```json
{
  "type": "app",
  "appId": 1091500,
  "name": "Cyberpunk 2077",
  "url": "https://store.steampowered.com/app/1091500/",
  "appType": "game",
  "isFree": false,
  "price": 59.99,
  "originalPrice": 59.99,
  "currency": "USD",
  "discountPercent": 0,
  "releaseDate": "Dec 9, 2020",
  "comingSoon": false,
  "developers": ["CD PROJEKT RED"],
  "publishers": ["CD PROJEKT RED"],
  "genres": ["RPG"],
  "categories": ["Single-player", "Steam Achievements", "Full controller support"],
  "tags": ["Cyberpunk", "Open World", "Nudity", "RPG", "Futuristic"],
  "platforms": ["windows", "mac"],
  "metacriticScore": 86,
  "recommendationsTotal": 800000,
  "achievementsCount": 57,
  "dlcCount": 2,
  "requiredAge": 17,
  "supportedLanguages": ["English", "French", "German"]
}
```

### How to scrape Steam reviews for a game

Set **Mode** to `reviews` and paste the app ID (the number in the store URL, `store.steampowered.com/app/570/...`). Reviews are read newest first, 100 per page, until **Max items**, **Max reviews per app** or the end of the list is reached, so a full history export of a game with 50,000 reviews takes 500 requests. Use **Review language** `english` to keep only English text, **Review type** `negative` to mine complaints, and **Reviews order** `all` to get Steam's most-helpful reviews first. The `summary` item gives the global totals so you can compute the positive ratio without downloading everything.

### Monitor changes on a schedule

Turn on **Only new or changed items** and save the input as a task with a Schedule (Apify Console: **Saved tasks** -> **Schedule**, for example daily). Each run then remembers what earlier runs of the same input returned and outputs only what is new: new reviews in `reviews` mode, and apps whose price, discount or release date changed in `details` and `search` mode. Unchanged items are skipped before they are saved, so they are not charged; the per-app review summary is output on the first run only. Add **Only reviews newer than** (`2 days`, `24 hours` or a date like `2026-10-01`) to bound how far back the first run reads; reviews are then read newest first and paging stops as soon as a page reaches older or already-seen reviews. Monitored items carry `changeType` (`new` or `changed`) and, for changed apps, `previousValues` with the old values of the fields that changed (e.g. `{"price": 19.99}`). Use **Monitoring key** to keep several schedules on the same input apart.

### Does it work without a Steam account or API key?

Yes. Everything comes from the public store endpoints that the Steam website itself calls when you browse logged out; no Steam Web API key, account, session or cookies from your browser are needed. Mature (age-gated) games are handled automatically.

### How to get Steam game prices and discounts

Use **Mode** `details` with the app IDs and set **Country code** to the store region you care about (`us`, `gb`, `de`, `br`, `jp`, ...). Each app item carries `price`, `originalPrice`, `discountPercent` and `currency` for that region, plus `isFree` and `comingSoon`. Schedule the Actor to track sales over time. For a quick overview of many games, **Mode** `search` returns price, discount and review score for every result in one request per 100 games.

### Can I get Steam user tags, genres and Metacritic scores?

Yes. `details` mode returns the top 20 user-applied tags (`tags`, with vote counts in `tagsDetailed`), store `genres` and `categories`, `metacriticScore`, `recommendationsTotal`, `achievementsCount`, DLC IDs, supported languages, screenshots and trailer links.

### What does it cost?

Pay per item: a review costs a fraction of a cent (a summary item is charged as one review), an app-details item a little more because it needs two requests, and a search result sits in between. There is no start fee and no subscription; Apify's free plan is enough to collect tens of thousands of reviews.

### Integrations and API

Use the run in Zapier, Make, n8n, Google Sheets, or call it from Python/Node with the Apify client. See the **API** tab for ready-made snippets, or schedule the Actor to keep a review feed or price history fresh.

### Is it legal to scrape Steam?

This Actor collects only publicly available data that Steam shows to anyone without an account: store listings, prices and user reviews. For each review it exports the reviewer identity Steam shows next to the review: display (persona) name, public profile link, custom profile handle when set, and Steam ID, plus the playtime and library/review counts Steam prints on the review. It does not log in, does not open user profiles and does not collect avatars, online status, emails or other contact details. Reviewer names, handles, profile links and Steam IDs are personal data under GDPR and similar laws: make sure you have a lawful basis for processing them, and do not use them to contact or profile individuals. You are responsible for how you use the data and for complying with Steam's terms and applicable law.

### Support

Found a bug or need a field added? Open an issue in the **Issues** tab; it is usually answered within a day.

### Related scrapers

- [IMDb Scraper](https://apify.com/tortuga/imdb-scraper): Movies, TV, Ratings & Reviews
- [Letterboxd Scraper](https://apify.com/tortuga/letterboxd-scraper): Films, Reviews, Ratings & Lists
- [Metacritic Scraper](https://apify.com/tortuga/metacritic-scraper): Metascores, Reviews, Games & Movies
- [Goodreads Scraper](https://apify.com/tortuga/goodreads-scraper): Books, Reviews, Authors & Lists
- [Shopify App Store Scraper](https://apify.com/tortuga/shopify-app-store-scraper): Apps, Pricing, Reviews & Developers

### Found it useful?

A ★ review on this Actor's Apify Store page helps other users find it and tells us what to improve. Issues and feature requests are welcome in the Actor's **Issues** tab.

# Actor input Schema

## `mode` (type: `string`):

What to scrape. `reviews`: user reviews (plus one review-summary item) for each app in **App IDs**. `details`: one app item per app with price, tags, genres, release date and more. `search`: store search results for each term in **Search terms**.

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

Steam app IDs or store URLs, one per line: `570`, `https://store.steampowered.com/app/730/Counter-Strike_2/`. Used by the `reviews` and `details` modes. Find the ID in the store URL of the game.

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

Search queries for the `search` mode, one per line, e.g. `hollow knight`, `roguelike deckbuilder`. Each term returns the same list as the store search page, up to **Max items**.

## `maxItems` (type: `integer`):

Overall cap on dataset items for the run (reviews + summaries, apps, or search results). Keeps cost predictable.

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

Cap on reviews collected from each app in `reviews` mode. Leave empty to use only **Max items**.

## `reviewsFilter` (type: `string`):

`recent`: newest first (default, full history reachable). `updated`: by last edit. `all`: Steam's helpfulness order, which surfaces the most-voted reviews first.

## `reviewLanguage` (type: `string`):

Steam language code, e.g. `all`, `english`, `german`, `schinese`, `russian`, `brazilian`, `japanese`, `koreana`, `spanish`, `french`. Only reviews written in that language are returned.

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

Return all reviews, only recommended (thumbs up) or only not recommended (thumbs down).

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

`steam`: reviews by people who bought the game on Steam. `non_steam_purchase`: reviews from keys activated on Steam. `all`: both.

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

Two-letter store region for prices and currency in `details` and `search` modes, e.g. `us`, `gb`, `de`, `br`, `jp`.

## `reviewsNewerThan` (type: `string`):

Only reviews newer than: a date (YYYY-MM-DD) or a period such as '7 days' or '24 hours'. Reviews are then read newest first and paging stops at the first page that reaches older reviews, so a daily run reads only a page or two per app. Leave empty for no date limit. `reviews` mode only.

## `onlyNewOrChanged` (type: `boolean`):

Remember what earlier runs of this input returned and output only new items: new reviews in `reviews` mode (read newest first; paging stops where the previous run's reviews begin), apps whose price, discount or release date changed in `details` and `search` mode. Use with a Schedule; unchanged items are not charged. The per-app review summary is output on the first run only.

## `monitoringKey` (type: `string`):

Name for this watch, so several schedules on the same search stay separate; defaults to a key derived from the search input. Only used with **Only new or changed items**.

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

Apify Proxy is recommended for larger runs; Steam rate-limits the app-details endpoint per IP (about 200 requests per 5 minutes).

## Actor input object example

```json
{
  "mode": "reviews",
  "appIds": [
    "570",
    "https://store.steampowered.com/app/730/Counter-Strike_2/"
  ],
  "searchTerms": [
    "hollow knight"
  ],
  "maxItems": 500,
  "reviewsFilter": "recent",
  "reviewLanguage": "all",
  "reviewType": "all",
  "purchaseType": "all",
  "countryCode": "us",
  "onlyNewOrChanged": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (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",
        "https://store.steampowered.com/app/730/Counter-Strike_2/"
    ],
    "searchTerms": [
        "hollow knight"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("tortuga/steam-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",
        "https://store.steampowered.com/app/730/Counter-Strike_2/",
    ],
    "searchTerms": ["hollow knight"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("tortuga/steam-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",
    "https://store.steampowered.com/app/730/Counter-Strike_2/"
  ],
  "searchTerms": [
    "hollow knight"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call tortuga/steam-scraper --silent --output-dataset

```

## MCP server setup

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