# Steam Reviews Scraper & Price Monitor - New Reviews, Sales (`neverempty/steam-reviews-price-monitor`) Actor

For game developers and publishers: Steam reviews (text, recommended or not, language, date, playtime, helpful votes, developer reply), the review summary and store data (price, discount, release date, genres). Monitoring mode returns only new reviews and price, discount or score changes.

- **URL**: https://apify.com/neverempty/steam-reviews-price-monitor.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** E-commerce, Social media, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 review returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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 & Price Monitor - New Reviews, Sales

Read the reviews, the review summary and the store data (price, discount, release date, genres, developer) of any game on Steam. Turn on **monitoring mode** and each scheduled run returns only what is new: reviews added since the last run, and a game row only when its price, discount, review totals or review score moved.

Built for game developers, publishers and marketers who check their own games and their competitors every day. No Steam account and no API key.

### What you get

**Review rows** (`type: "review"`), newest first:

| Field | Example |
| --- | --- |
| `appId`, `gameName`, `storeUrl` | `1245620`, `ELDEN RING` |
| `reviewId` | `236967502` |
| `recommended` | `true` (thumbs up) or `false` (thumbs down) |
| `language` | `english` |
| `reviewText` | `Great game, runs well on my laptop.` |
| `createdAt`, `updatedAt`, `edited` | `2026-10-05T09:17:06.000Z`, same, `false` |
| `playtimeAtReviewMinutes`, `playtimeForeverMinutes`, `playtimeLastTwoWeeksMinutes` | `1830`, `2415`, `442` |
| `votesHelpful`, `votesFunny`, `helpfulnessScore`, `commentCount` | `37`, `5`, `0.578`, `0` |
| `steamPurchase`, `receivedForFree`, `refunded`, `writtenDuringEarlyAccess`, `primarilySteamDeck` | `true`, `false`, `false`, `false`, `false` |
| `reviewerGamesOwned`, `reviewerReviewCount` | `112`, `9` |
| `developerResponse`, `developerResponseAt` | the developer's reply and its time, or `null` |

**Game rows** (`type: "game"`), one per game:

- store data: `name`, `appType`, `isFree`, `currency`, `priceInitial`, `priceFinal`, `discountPercent`, `priceFormatted`, `releaseDate`, `releaseDateText`, `comingSoon`, `genres`, `categories`, `developers`, `publishers`, `platforms`, `metacriticScore`, `requiredAge`, `shortDescription`, `headerImage`, `website`, `countryCode`
- review summary: `totalReviews`, `totalPositive`, `totalNegative`, `positivePercent`, `reviewScore`, `reviewScoreDesc` (for example `Very Positive`)

The review summary counts reviews in all languages and from all purchase types (Steam purchases and keys activated on Steam), as Steam reports them.

Measured on 2026-10-05: reviews came newest first, 100 per request; a game with 93 reviews returned exactly 93 across its pages; price for the same game was `59.99 USD` with country `us` and `9020 JPY` with country `jp`.

### Input

- **Games**: store URLs (`https://store.steampowered.com/app/1245620/ELDEN_RING/`) or app IDs (`1245620`).
- **Store country**: two-letter code (`us`, `gb`, `de`, `jp`, `br` ...). Price and currency depend on it. If left empty, `us` is used and every row says so in `countryCode`.
- **Review language**: all languages, or one Steam language.
- **Maximum reviews per game** (default 100), **Return reviews**, **Monitoring mode**, **Forget what was seen before**.

```json
{
  "games": ["1245620", "https://store.steampowered.com/app/413150/Stardew_Valley/"],
  "countryCode": "us",
  "maxReviewsPerGame": 100,
  "monitoringMode": true
}
```

### Monitoring mode

1. The first run returns the current state (game row and newest reviews) marked `change: "first-check"` and remembers it.
2. Every later run with the same games, country and language returns only:
   - reviews that were not returned before (`change: "new-review"`), oldest first,
   - the game row when any of `priceFinal`, `priceInitial`, `discountPercent`, `isFree`, `currency`, `totalReviews`, `totalPositive`, `totalNegative`, `reviewScoreDesc` or `storeAvailable` changed, with `changedFields` and the previous values (`previousPriceFinal`, `previousDiscountPercent`, `previousTotalReviews`, `previousTotalPositive`, `previousTotalNegative`, `previousReviewScoreDesc`).
3. A game with nothing new returns no rows. The run status then says `no-new-since-last-run`.

Only rows that were actually delivered are remembered, so if a run stops at your spending limit, or a game got more new reviews than **Maximum reviews per game**, the remaining new reviews arrive with the next run. Schedule it daily and send the dataset to Slack, email or a sheet with an Apify integration to catch a competitor's sale or a wave of negative reviews the day it starts.

Limits to know: on a busy game the review totals move every day, so its game row comes back on most runs. An edited review keeps its id and is not returned again. A review deleted by its author is not reported. One run looks back at most 5,000 reviews per game for new ones. If two runs with the same input finish at the same moment, one may not see what the other remembered.

### When something cannot be returned

You are never charged for a row that explains a problem. These come back as free rows with `type: "note"`:

- `app-not-found`: Steam has no store entry for that app ID in that country and no reviews for it. The ID may not exist, the game may not be sold there, or the page may be age-gated behind sign-in.
- `not-available-in-country`: the game has reviews but no store entry in that country (or it is age-gated behind sign-in). Reviews and the review summary are still returned; store fields are empty and `storeAvailable` is `false`.
- `app-redirected`: Steam answered with a different app's store entry.
- `invalid-input`, `duplicate-input`, `no-input`.
- `blocked`: Steam answered with a rate limit or a refusal twice in a row. The run stops and does not try to get around it.
- `unreadable`: the answer did not look as expected, so nothing is claimed about it.
- `more-new-reviews`, `disallowed-by-robots`, `robots-unreadable`.

### What this Actor does not do

- No reviewer identity. The SteamID, display name, avatar and profile URL of the person who wrote a review are never returned, only the review and its numbers.
- No sign-in, no age-gate bypass, no proxy rotation and no CAPTCHA solving.
- No player counts and no Steam Web API: the robots.txt of api.steampowered.com disallows automated access. This Actor reads the robots.txt of store.steampowered.com on every run and requests only URLs it allows.
- An unknown two-letter country code is refused instead of silently returning US prices.

### Pricing

Pay per result: you pay for each review row and each game row that is delivered. In monitoring mode a game with nothing new costs one small check fee instead. Note rows are free. There is no start fee.

### Notes

This is an unofficial tool. It is not affiliated with, endorsed by or sponsored by Valve Corporation. Steam is a trademark of Valve Corporation. It reads only public store data. Review text is written by Steam users; check Steam's terms and the law that applies to you before republishing it.

### Thanks for using this Actor

We build these tools for people who run them every day, and we improve them from what users tell us.

- **Missing a field, or need another filter?** Tell us in the **Issues** tab. If the data is there, we add it.
- **Found a bug or a wrong value?** Post the run ID in the **Issues** tab. Wrong data is the thing we fix first.

If this Actor saved you time, a short review helps other people find it.

# Actor input Schema

## `games` (type: `array`):

Games to read: the store URL such as https://store.steampowered.com/app/1245620/ELDEN_RING/, or just the app ID (the number in that URL), such as 1245620. For each game you get one game row (name, price, discount, release date, genres, developer, review totals and score) and its newest reviews.

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

Steam shows a different price and currency per country. Use a two-letter country code such as us, gb, de, jp or br. If left empty, prices are read for us (USD); every row says which country it was read for. A game that is not sold in that country comes back without store fields and with a free note row.

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

Return only reviews written in this language. The review totals and score on the game row always cover all languages.

## `includeReviews` (type: `boolean`):

Turn off to get only the game row (price, discount, review totals and score) for each game.

## `maxReviewsPerGame` (type: `integer`):

Newest reviews first, 100 per request. In monitoring mode this is the most new reviews returned per game per run; the rest come with the next run.

## `monitoringMode` (type: `boolean`):

The first run returns the current state and remembers it. Every later run with the same games, country and language returns only reviews added since then, and a game row only when its price, discount, review totals or review score changed (with the previous values). A game with nothing new returns no rows and costs one small check fee.

## `resetMonitoringState` (type: `boolean`):

Clears the remembered state for the games in this input (for this country and language) before the run, so the run behaves like a first run for them.

## Actor input object example

```json
{
  "games": [
    "1245620",
    "https://store.steampowered.com/app/413150/Stardew_Valley/"
  ],
  "countryCode": "us",
  "reviewLanguage": "all",
  "includeReviews": true,
  "maxReviewsPerGame": 100,
  "monitoringMode": false,
  "resetMonitoringState": false
}
```

# Actor output Schema

## `results` (type: `string`):

Review rows (text, recommended or not, language, dates, playtime, helpful votes, developer reply) and game rows (name, price, currency, discount, release date, genres, developer, review totals and score) from the Steam store. Games that do not exist or are not sold in the chosen country, blocked or unreadable answers and invalid input come back as free rows that say why.

# 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 = {
    "games": [
        "1245620",
        "https://store.steampowered.com/app/413150/Stardew_Valley/"
    ],
    "countryCode": "us"
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/steam-reviews-price-monitor").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 = {
    "games": [
        "1245620",
        "https://store.steampowered.com/app/413150/Stardew_Valley/",
    ],
    "countryCode": "us",
}

# Run the Actor and wait for it to finish
run = client.actor("neverempty/steam-reviews-price-monitor").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 '{
  "games": [
    "1245620",
    "https://store.steampowered.com/app/413150/Stardew_Valley/"
  ],
  "countryCode": "us"
}' |
apify call neverempty/steam-reviews-price-monitor --silent --output-dataset

```

## MCP server setup

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

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/r6HwBOoXbAFFmRuZ5/builds/tp0yEmMgasl1w6WQg/openapi.json
