# Steam Games, Prices & Reviews Scraper (`xtracto/steam-store-scraper`) Actor

Scrape the Steam store: search 277k+ products, full game metadata with price and discount, and cursor-paged user reviews with playtime. Regional pricing via country code. No key, no login.

- **URL**: https://apify.com/xtracto/steam-store-scraper.md
- **Developed by:** [Farhan Febrian Nauval](https://apify.com/xtracto) (community)
- **Categories:** E-commerce, Videos
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 results

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?

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 Games, Prices & Reviews Scraper

Pull structured data from the **Steam store** — the largest PC games marketplace. Search **277,000+ products**, get full game metadata with regional pricing, or collect user reviews complete with the reviewer's playtime.

### Why Use This Actor?

- **Three jobs in one actor.** Search the catalogue, fetch full game details, or page through reviews — same input shape, same output envelope.
- **Regional pricing.** One `country` code switches the storefront, so you can compare the same title across US, UK, German, Brazilian or Indonesian pricing.
- **Playtime-weighted reviews.** Every review carries `playtimeAtReviewHours` — you can tell a 2-hour hot take from a 1,000-hour verdict, which plain star ratings can't.
- **Discount tracking.** `discountPercent`, `originalPriceFormatted` and `priceFormatted` make sale monitoring a one-line filter.
- **Honest nulls.** A free or region-unavailable title returns `priceCents: null`, never a misleading `0`.
- **No key, no login, no browser.** These are the same endpoints the store's own pages call.

### What It's Good For

- **Market research** — how many roguelikes shipped this year, at what price, with what reception?
- **Price and sale monitoring** — track discounts across a wishlist or a publisher's catalogue.
- **Competitor analysis** — line up a rival's review sentiment, tags and pricing against yours.
- **Review mining** — sentiment and feature complaints, weighted by how long the reviewer actually played.
- **Regional pricing studies** — purchasing-power comparisons across storefronts.

### Input

| Parameter | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search`, `detail` or `reviews`. |
| `searchTerm` | string | – | Keyword for `search` mode. Empty lists the whole store. |
| `appIds` | array | – | App IDs for `detail`/`reviews`. Store URLs are accepted and parsed. |
| `tagIds` | array | – | Steam tag IDs to filter a search. |
| `onlySpecials` | boolean | `false` | Restrict a search to titles on sale. |
| `country` | string | `us` | Two-letter code driving regional price and currency. |
| `language` | string | `english` | Store language. |
| `reviewFilter` | string | `recent` | `recent`, `updated` or `all` (most helpful). |
| `reviewType` | string | `all` | `all`, `positive`, `negative`. |
| `purchaseType` | string | `all` | `all`, `steam`, `non_steam_purchase`. |
| `reviewLanguage` | string | `all` | Review language filter. |
| `maxItems` | integer | `200` | Record cap. In `reviews` mode it is split evenly across the app IDs. |

#### Example — find discounted roguelikes

```json
{ "mode": "search", "searchTerm": "roguelike", "onlySpecials": true, "country": "us", "maxItems": 200 }
```

#### Example — reviews for Counter-Strike 2

```json
{ "mode": "reviews", "appIds": ["730"], "reviewFilter": "recent", "reviewLanguage": "english", "maxItems": 500 }
```

### Output

**Search / detail row:**

```json
{
  "appId": 4075620,
  "title": "Combolands: Roguelike Citybuilder",
  "url": "https://store.steampowered.com/app/4075620/Combolands_Roguelike_Citybuilder/",
  "releaseDate": "Aug 24, 2026",
  "platforms": ["win"],
  "priceCents": 799,
  "priceFormatted": "$7.99",
  "originalPriceFormatted": "$9.99",
  "discountPercent": 20,
  "reviewSummary": "Very Positive",
  "reviewPositivePercent": 96,
  "reviewCount": 204,
  "tagIds": [9, 1716, 3959],
  "_mode": "search"
}
```

**Review row:**

```json
{
  "appId": 730,
  "recommendationId": "198234771",
  "votedUp": true,
  "review": "Skill ceiling is high, hard to learn, fun with friends.",
  "createdAt": "2026-08-26T09:14:02+00:00",
  "votesUp": 3,
  "steamPurchase": true,
  "refunded": false,
  "onSteamDeck": false,
  "authorName": "player123",
  "authorGamesOwned": 214,
  "playtimeAtReviewHours": 1154.7,
  "playtimeForeverHours": 1201.3,
  "appReviewScoreDesc": "Very Positive",
  "appTotalPositive": 1277397,
  "appTotalNegative": 221211,
  "appTotalReviews": 2601715,
  "_mode": "reviews"
}
```

#### Field reference — selected

| Field | Type | Description |
|---|---|---|
| `priceCents` | integer | Final price in minor units (799 = $7.99). `null` when free or unpriced in that region — never `0`. |
| `discountPercent` | integer | Current discount; `0` when not on sale. |
| `reviewPositivePercent` / `reviewCount` | integer | Parsed from the store's own review tooltip. |
| `recommendationTotal` | integer | Steam's lifetime recommendation count (detail mode). |
| `playtimeAtReviewHours` | number | Hours played when the review was written. Steam reports minutes; this is converted. |
| `appTotalPositive` / `appTotalNegative` | integer | Whole-game review totals, repeated on each review row for convenience. |
| `_mode` | string | Which mode produced the row. |
| `_error` | string | Present only on failures (`no_app_ids`, `app_unavailable`, `reviews_unavailable`, `blocked`, `http_*`). |

### Known Limits

- **Search caps out per query.** Very broad searches page deeply but slowly; narrow with tags, price or `onlySpecials` for large sweeps.
- **`detail` mode is one request per app.** Steam's endpoint accepts a list but only returns data for a single app, so large ID sets take proportionally longer.
- **Delisted or region-locked apps** return an `app_unavailable` error row rather than an empty record — that's deliberate, so gaps are visible.
- **Review author IDs are public profile data.** `authorGamesOwned` reads `0` for users with a private profile; that's the source's value, not a parse failure.
- **No owner or sales estimates.** Steam does not publish unit sales; `recommendationTotal` and review counts are proxies, not sales figures.

### Scope & Compliance

- **Public store data only.** Every endpoint used is one Steam's own public store pages call for anonymous visitors. No key, no login, no credentials.
- **Reviews are public, attributed content.** The actor collects the public display name and profile link Steam already shows on each review; it collects no emails, no private contact details and no data from private profiles.
- **No security control is defeated.** Ordinary HTTPS requests with a browser-accurate TLS fingerprint. No CAPTCHA solving, no forged authentication.
- **Rate limits are respected.** Requests are paced between pages.
- Use the output in line with Valve's Steam Terms of Service and applicable law.

### Related Actors

| Actor | What it covers |
|---|---|
| [`appstore-reviews-scraper`](https://apify.com/xtracto/appstore-reviews-scraper) | Apple App Store reviews |
| [`google-play-reviews-scraper`](https://apify.com/xtracto/google-play-reviews-scraper) | Google Play reviews |
| [`twitch-channel`](https://apify.com/xtracto/twitch-channel) | Twitch channel data |
| [`kickstarter-discovery`](https://apify.com/xtracto/kickstarter-discovery) | Crowdfunded game projects |

# Actor input Schema

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

search = find games by keyword or tag. detail = full metadata for specific app IDs. reviews = user reviews for specific app IDs.

## `searchTerm` (type: `string`):

Keyword to search the store for, e.g. 'roguelike', 'city builder'. Leave empty to list the whole store.

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

Steam app IDs for detail and reviews mode. A full store URL works too - https://store.steampowered.com/app/730/ is read as 730.

## `tagIds` (type: `array`):

Optional Steam tag IDs to filter a search, taken from the tags parameter of a Steam search URL.

## `onlySpecials` (type: `boolean`):

Restrict a search to titles currently on sale.

## `country` (type: `string`):

Two-letter country code controlling regional pricing and currency, e.g. us, gb, de, id, br.

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

Store language for names and descriptions, e.g. english, german, spanish.

## `reviewFilter` (type: `string`):

How reviews are ordered in reviews mode.

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

Limit reviews to positive or negative only.

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

Limit reviews to verified Steam purchases, or include keys activated elsewhere.

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

Review language filter, e.g. english, all.

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

Maximum records to return. In reviews mode this budget is split evenly across the app IDs given.

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

Optional. Steam answers plain HTTP; a proxy is only useful for very large runs or to check another region's storefront.

## Actor input object example

```json
{
  "mode": "search",
  "searchTerm": "roguelike",
  "appIds": [
    "730"
  ],
  "onlySpecials": false,
  "country": "us",
  "language": "english",
  "reviewFilter": "recent",
  "reviewType": "all",
  "purchaseType": "all",
  "reviewLanguage": "all",
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `appId` (type: `string`):

App Id as reported by the source.

## `title` (type: `string`):

Title of the item.

## `priceFormatted` (type: `string`):

Price as displayed by the source.

## `discountPercent` (type: `string`):

Discount percentage; 0 when not on sale. Whole number.

## `reviewSummary` (type: `string`):

Summary label for the review score.

## `reviewPositivePercent` (type: `string`):

Review Positive Percent as reported by the source.

## `reviewCount` (type: `string`):

Number of reviews. Whole number.

## `releaseDate` (type: `string`):

Release Date as reported by the source.

## `url` (type: `string`):

Direct link to the scraped item.

## `platforms` (type: `string`):

Platforms.

## `priceCents` (type: `string`):

Price Cents.

## `originalPriceFormatted` (type: `string`):

Original Price Formatted as reported by the source.

## `recommendationId` (type: `string`):

Recommendation Id as reported by the source.

## `votedUp` (type: `string`):

Voted Up as reported by the source.

## `review` (type: `string`):

Review as reported by the source.

## `createdAt` (type: `string`):

Creation timestamp, ISO 8601.

## `votesUp` (type: `string`):

Votes Up as reported by the source.

## `steamPurchase` (type: `string`):

Steam Purchase as reported by the source.

## `refunded` (type: `string`):

Refunded as reported by the source.

## `onSteamDeck` (type: `string`):

On Steam Deck as reported by the source.

## `authorName` (type: `string`):

Author Name as reported by the source.

## `authorGamesOwned` (type: `string`):

Author Games Owned as reported by the source.

## `playtimeAtReviewHours` (type: `string`):

Playtime At Review Hours.

## `playtimeForeverHours` (type: `string`):

Playtime Forever Hours.

## `appReviewScoreDesc` (type: `string`):

App Review Score Desc as reported by the source.

## `appTotalPositive` (type: `string`):

App Total Positive as reported by the source.

## `appTotalNegative` (type: `string`):

App Total Negative as reported by the source.

## `appTotalReviews` (type: `string`):

App Total Reviews.

## `recommendationTotal` (type: `string`):

Recommendation Total. Whole number.

## `updatedAt` (type: `string`):

Last-updated timestamp, ISO 8601.

## `votesFunny` (type: `string`):

Votes Funny as reported by the source.

## `weightedVoteScore` (type: `string`):

Weighted Vote Score as reported by the source.

# 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 = {
    "mode": "search",
    "searchTerm": "roguelike",
    "appIds": [
        "730"
    ],
    "country": "us",
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("xtracto/steam-store-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 = {
    "mode": "search",
    "searchTerm": "roguelike",
    "appIds": ["730"],
    "country": "us",
    "maxItems": 50,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("xtracto/steam-store-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 '{
  "mode": "search",
  "searchTerm": "roguelike",
  "appIds": [
    "730"
  ],
  "country": "us",
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call xtracto/steam-store-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,xtracto/steam-store-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/pauK4wryZiqePr8vB/builds/jE2F1Ivib6VPJ6zye/openapi.json
