# Stream Reviews Scraper (`reviewly/stream-reviews-scraper`) Actor

Scrape reviews from any Steam game to JSON, CSV or Excel. Get review text, rating, playtime, votes, awards and reviewer profiles, plus game price, tags and developer — no login or API key. Supports 29 languages, age-gated titles and incremental daily run

- **URL**: https://apify.com/reviewly/stream-reviews-scraper.md
- **Developed by:** [Reviewly](https://apify.com/reviewly) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.95 / 1,000 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 — Export Steam Game Reviews to JSON, CSV & Excel

**Scrape every public review from any game on Steam in seconds — no login, no API key, no coding.** Paste a Steam URL or App ID, press Start, and download clean, structured review data.

- ⚡ **Fast** — around 750 reviews per minute, per game
- 🔓 **No Steam account needed** — age gates and mature-content walls are handled automatically
- 🌍 **29 languages** — filter reviews by language, or grab them all
- 📊 **35+ data points** per review and per game, ready for analysis
- 💾 **Export anywhere** — JSON, CSV, Excel, XML, or straight into your app via API

***

### 📌 What This Actor Does

This Apify Actor is a **Steam review scraper**. Give it a Steam game — as a store link, a community link, or just the numeric App ID — and it collects that game's public user reviews along with the game's store metadata.

For every review you get the verdict (Recommended or Not Recommended), the full review text, the reviewer's total playtime, how many people found it helpful or funny, community awards, comment count, and the reviewer's public profile. For every game you get the name, developer, publisher, release date, price, tags, and the overall review score.

#### Who it's for

| You are | You use it to |
|---|---|
| **Game developer / publisher** | Read what players actually say about your game or your competitors' |
| **Market researcher / analyst** | Measure sentiment across genres, studios, or a launch window |
| **Data scientist / ML engineer** | Build labelled sentiment datasets with real playtime signals |
| **Community / marketing manager** | Track review trends, spot complaints early, find quotable praise |
| **Journalist / content creator** | Source real player opinions with links back to the original review |
| **Student / academic** | Research player behaviour with reproducible, citable data |

No programming is required. If you can copy a link, you can run this Actor.

***

### ✨ Key Features

- **Two ways to enter games** — paste Steam URLs *or* plain App IDs. Mix both if you like; a game entered twice is only scraped once.
- **Bulk scraping** — queue as many games as you want in a single run.
- **Automatic age-gate bypass** — mature and age-restricted games (The Witcher 3, Cyberpunk 2077, PUBG) work exactly like any other, with no cookies or logins to configure.
- **8 sorting modes** — most helpful, most recent, funniest, or trending over day / week / month / 6 months / year.
- **Filter by language** — pick one of 29 review languages, or collect every language at once.
- **Incremental runs** — set a target date and re-run daily to pull only what's new, instead of re-scraping everything.
- **Full reviewer profiles** — display name, Steam ID (64-bit), profile URL, avatar, and games owned.
- **Clean, typed output** — real numbers for votes and playtime, ISO dates, booleans for the verdict. No string-parsing on your end.
- **Honest nulls** — a field Steam doesn't publish comes back `null`, never a guess or an empty string.
- **Proxy support** — optional Apify Proxy integration for large or repeated runs.

***

### 🧠 Why This Actor Is Different

**It reads Steam's real pagination, so nothing gets skipped.** Steam serves reviews through a cursor-based endpoint rather than numbered pages. This Actor follows that cursor exactly and stops only when Steam signals the true end of the list — so you don't get duplicates, and you don't silently lose the tail of the results.

**Age-restricted games just work.** Steam blocks a large share of its biggest titles behind an age check and a mature-content warning. That warning returns a normal-looking `200 OK` page containing zero reviews — scrapers that check status codes think they succeeded and return nothing. This Actor detects it properly and gets the real data.

**Stable review IDs.** Steam doesn't put a review ID on the review card itself. This Actor recovers the real `recommendationid` for every review, so you can deduplicate reliably across runs and link straight back to the source review.

**Correct dates.** Steam omits the year on reviews posted in the current year. Naïve scrapers record those as the wrong year, or drop them. Here every review gets a proper ISO `YYYY-MM-DD` date.

**Lightweight and quick.** No headless browser is used, so runs start instantly and consume far fewer platform resources than browser-based scrapers — which means lower cost per review for you.

***

### ⚙️ Input Configuration

| Field | Type | Default | Description |
|---|---|---|---|
| `startUrls` | Array | — | Steam store or community URLs |
| `appIds` | Array | — | Steam numeric App IDs, one per line |
| `maxReviews` | Integer | `100` | Max reviews **per game**. `0` = unlimited |
| `reviewFilter` | String | `toprated` | Sort order (see below) |
| `reviewLanguage` | String | `default` | Review language. `default` = all languages |
| `targetDate` | String | — | Skip reviews older than this date (`YYYY-MM-DD`) |
| `includeGameInfo` | Boolean | `true` | Also fetch game metadata from the store page |
| `proxyConfiguration` | Object | — | Optional proxy settings |

#### Choosing games: URLs or App IDs

Fill in **either** field — or both. At least one is required.

The **App ID** is the number in any Steam store link:
`store.steampowered.com/app/`**`292030`**`/`

```jsonc
// Option A — just App IDs (simplest)
{ "appIds": ["292030", "440", "578080"] }

// Option B — just URLs
{ "startUrls": ["https://store.steampowered.com/app/292030/"] }

// Option C — mix them freely
{ "startUrls": ["https://store.steampowered.com/app/292030/"], "appIds": ["440"] }
```

Every Steam link shape is accepted:

```
https://store.steampowered.com/app/292030/
https://store.steampowered.com/app/292030/The_Witcher_3_Wild_Hunt/
https://steamcommunity.com/app/292030/reviews/
https://store.steampowered.com/agecheck/app/292030/
```

#### Sorting options (`reviewFilter`)

| Value | Returns |
|---|---|
| `toprated` | Most helpful reviews of all time **(default)** |
| `mostrecent` | Newest reviews first |
| `funny` | Reviews voted funniest |
| `trendday` | Trending in the last 24 hours |
| `trendweek` | Trending this week |
| `trendmonth` | Trending this month |
| `trendsixmonths` | Trending over 6 months |
| `trendyear` | Trending this year |

#### Languages (`reviewLanguage`)

`default` (all) plus: English, French, German, Spanish (Spain & Latin America), Italian, Portuguese (& Brazil), Russian, Polish, Turkish, Dutch, Danish, Swedish, Norwegian, Finnish, Czech, Hungarian, Romanian, Bulgarian, Greek, Ukrainian, Japanese, Korean, Simplified Chinese, Traditional Chinese, Thai, Vietnamese, Indonesian.

#### 💡 Tips for best results

- **Start small.** Run with `maxReviews: 20` first to confirm you're getting what you expect, then scale up.
- **For sentiment analysis**, use `toprated` — these are the reviews the community actually reads and votes on.
- **For monitoring a launch or an update**, use `mostrecent`.
- **`targetDate` only cuts a run short under `mostrecent`**, because that's the only date-sorted option. Under other sorts it filters rows but still walks the full list.
- **Turn off `includeGameInfo`** if you only need review text — it saves one request per game.
- **Set `maxReviews: 0`** only when you genuinely want everything; popular games have hundreds of thousands of reviews.

#### Example input

```json
{
  "appIds": ["292030", "1091500"],
  "maxReviews": 500,
  "reviewFilter": "mostrecent",
  "reviewLanguage": "english",
  "targetDate": "2025-01-01",
  "includeGameInfo": true
}
```

***

### 📤 Output Format

The Actor produces **one dataset record per game**, with that game's reviews nested inside it. Download as JSON, CSV, Excel, or XML, or pull it through the Apify API.

#### Sample output

```json
{
  "appId": "292030",
  "url": "https://steamcommunity.com/app/292030/reviews/",
  "name": "The Witcher 3: Wild Hunt - Complete Edition",
  "developer": "CD PROJEKT RED",
  "publisher": "CD PROJEKT RED",
  "releaseDate": "18 May, 2015",
  "description": "You are Geralt of Rivia, mercenary monster slayer...",
  "reviewSummary": "Very Positive",
  "totalReviews": 241730,
  "positivePercent": 96,
  "price": "$34.99 USD",
  "priceCents": 3499,
  "tags": ["Open World", "RPG", "Story Rich", "Atmospheric"],
  "headerImage": "https://shared.fastly.steamstatic.com/.../header.jpg",
  "reviewsScraped": 1,
  "reviews": [
    {
      "reviewId": "87999031",
      "url": "https://steamcommunity.com/profiles/76561199061226139/recommended/292030/",
      "appId": "292030",
      "recommended": true,
      "voteTitle": "Recommended",
      "text": "Imagine you're working in a 9-5 corporate job...",
      "postedAt": "2021-03-06",
      "postedRaw": "March 6, 2021",
      "playtimeHours": 120.1,
      "helpfulVotes": 5034,
      "funnyVotes": 110,
      "awardCount": 661,
      "awards": [{ "reactionId": 18, "count": 207 }],
      "commentCount": 84,
      "earlyAccess": false,
      "receivedForFree": false,
      "author": {
        "name": "Dio1991",
        "profileUrl": "https://steamcommunity.com/profiles/76561199061226139/",
        "steamId": "76561199061226139",
        "accountId": "1100960411",
        "avatar": "https://avatars.fastly.steamstatic.com/cde80f50ba....jpg",
        "productsInAccount": 460
      }
    }
  ]
}
```

#### Game fields

| Field | Type | Description |
|---|---|---|
| `appId` | String | Steam App ID |
| `url` | String | Link to the game's review page |
| `name` | String | Game title |
| `developer` | String | Developer studio |
| `publisher` | String | Publisher |
| `releaseDate` | String | Release date as shown on Steam |
| `description` | String | Short store description |
| `reviewSummary` | String | Steam's verdict, e.g. "Very Positive" |
| `totalReviews` | Number | Total reviews the game has on Steam |
| `positivePercent` | Number | Percentage of all reviews that are positive |
| `price` | String | Displayed price, e.g. `"$34.99 USD"` or `"Free To Play"` |
| `priceCents` | Number | Price in cents (`0` for free-to-play) |
| `tags` | Array | Community tags |
| `headerImage` | String | Game header image URL |
| `reviewsScraped` | Number | How many reviews this run collected |
| `reviews` | Array | The reviews (below) |

#### Review fields

| Field | Type | Description |
|---|---|---|
| `reviewId` | String | Steam's stable review ID — use this to deduplicate |
| `url` | String | Direct link to the review on Steam |
| `recommended` | Boolean | `true` = Recommended, `false` = Not Recommended |
| `voteTitle` | String | The verdict as text |
| `text` | String | Full review text, paragraph breaks preserved |
| `postedAt` | String | Post date, ISO `YYYY-MM-DD` |
| `postedRaw` | String | Date exactly as Steam displayed it |
| `playtimeHours` | Number | Reviewer's total playtime, in hours |
| `helpfulVotes` | Number | People who found it helpful |
| `funnyVotes` | Number | People who found it funny |
| `awardCount` | Number | Total community awards |
| `awards` | Array | Award breakdown: `reactionId` + `count` |
| `commentCount` | Number | Comments on the review |
| `earlyAccess` | Boolean | Written during Early Access |
| `receivedForFree` | Boolean | Reviewer got the product free |
| `author.name` | String | Display name |
| `author.profileUrl` | String | Steam profile URL |
| `author.steamId` | String | 64-bit Steam ID |
| `author.accountId` | String | 32-bit account ID |
| `author.avatar` | String | Avatar image URL |
| `author.productsInAccount` | Number | Games owned (`null` if the profile is private) |

***

### ▶️ How to Use

#### Step 1 — Open the Actor

Click **Try for free** on the Apify Store page. You'll need a free Apify account.

#### Step 2 — Add your games

In the **Start URLs** field, paste a Steam store link. Or in **App IDs**, type the game's number (e.g. `292030`). Add as many as you want.

#### Step 3 — Set how many reviews

Set **Max reviews per game**. Start with `20`–`100` for a first test. Use `0` for everything.

#### Step 4 — Pick a sort order

**Most helpful** for quality opinions, **Most recent** for monitoring. Optionally set a language.

#### Step 5 — Run it

Click **Start**. Progress appears live in the log.

#### Step 6 — Download

Open the **Dataset** tab and export as **CSV**, **Excel**, **JSON**, or **XML** — or fetch it from the Apify API.

#### Common workflows

**One-off research export**

```json
{ "appIds": ["292030"], "maxReviews": 0, "reviewFilter": "toprated" }
```

**Daily monitoring (only new reviews)** — schedule this and move `targetDate` forward each run:

```json
{ "appIds": ["292030"], "maxReviews": 0, "reviewFilter": "mostrecent", "targetDate": "2025-06-01" }
```

**Competitor comparison**

```json
{ "appIds": ["292030", "1091500", "1245620"], "maxReviews": 300, "reviewFilter": "toprated" }
```

***

### 📈 Use Cases

#### 1. Competitor and market research

Pull the top reviews for every major game in your genre and find out what players consistently praise and complain about — before you commit to a roadmap.

#### 2. Player sentiment tracking after a release

Schedule a daily `mostrecent` run with a rolling `targetDate`. Watch sentiment shift hour by hour after a patch, a price change, or a controversy, and catch problems while they're still fixable.

#### 3. Training data for sentiment analysis

Each review ships with a human-labelled verdict (`recommended`) plus playtime and helpfulness votes. That's a high-quality, pre-labelled dataset for fine-tuning a sentiment model — far cleaner than scraped social media text.

#### 4. Marketing and community content

Filter for high `helpfulVotes` and `recommended: true` to surface your best quotable praise, each with a link back to the original review for attribution.

#### 5. Localisation and regional strategy

Run the same game across several `reviewLanguage` values and compare sentiment by market. A game loved in English and disliked in Simplified Chinese usually has a localisation or pricing problem worth finding.

#### 6. Academic and journalistic research

Reproducible, citable player-opinion data with stable IDs and source links — suitable for publication and peer review.

***

### 🛠️ Advanced Tips

#### Performance and throughput

Steam serves a maximum of **10 reviews per request** and this limit cannot be raised — so total time scales linearly with review count. Measured on a single game:

| Reviews | Requests | Time |
|---|---|---|
| 50 | 5 | ~5 seconds |
| 250 | 25 | ~20 seconds |
| 500 | 50 | ~38 seconds |
| 5,000 | 500 | ~6–7 minutes |

That's roughly **750 reviews per minute**. Budget accordingly for very popular games — a title with 240,000 reviews takes several hours to scrape completely.

#### Keeping costs down

- Cap `maxReviews` instead of using `0`. The most helpful 500 reviews usually tell you more than all 200,000.
- Set `includeGameInfo: false` when you only need review text.
- Use `targetDate` with `mostrecent` for repeat runs so you never pay to re-scrape the same reviews.

#### Proxy usage

Proxies are **optional**. For small and medium runs the Actor works fine without one. For very large or frequently repeated runs, enable **Apify Proxy** to avoid per-IP rate limiting:

```json
{ "proxyConfiguration": { "useApifyProxy": true } }
```

Datacenter proxies are sufficient — residential proxies are not required.

#### Scaling to many games

Put every App ID into one run rather than starting many runs. The Actor processes games sequentially, deduplicates them, and keeps going if one game fails.

#### Automation

Use **Apify Schedules** to run this daily or weekly, and **Webhooks** to push new reviews straight into your database, Google Sheets, or Slack when a run finishes.

***

### ❓ FAQ & Troubleshooting

**Do I need a Steam account or API key?**
No. The Actor only reads publicly visible reviews. There is nothing to log into and no key to configure.

**Does it work with age-restricted or mature games?**
Yes. Age checks and mature-content warnings are handled automatically. Games like The Witcher 3, Cyberpunk 2077 and PUBG work exactly like any other.

**Where do I find a game's App ID?**
It's the number in the store URL: `store.steampowered.com/app/`**`292030`**`/`. You can also paste the whole URL and skip the lookup.

**I got fewer reviews than I asked for.**
The game has fewer reviews than your `maxReviews`, or your `reviewLanguage` / `targetDate` filtered the rest out. Set `reviewLanguage: "default"` and clear `targetDate` to check.

**Why is `productsInAccount` sometimes `null`?**
Steam hides the games-owned count on private profiles. `null` means Steam didn't publish it — it isn't a scraping error.

**Why aren't the results sorted by `helpfulVotes`?**
`toprated` uses Steam's own weighted helpfulness score, which factors in the helpful-to-unhelpful ratio and recency — not the raw vote count. The order matches what you see on Steam. Sort by `helpfulVotes` yourself if you need a strict ranking.

**Can I get reviews between two specific dates?**
Use `reviewFilter: "mostrecent"` with `targetDate` as your start date, then filter the output for the end date.

**Can I scrape review comments or replies?**
Not currently — you get the comment *count* per review, not the comment threads.

**Is the review text complete or truncated?**
Complete. Full text with paragraph breaks preserved, including reviews that Steam collapses behind a "Read more" link.

**How do I avoid duplicates across scheduled runs?**
Deduplicate on `reviewId` — it's Steam's own stable identifier and never changes.

**One game failed. Did the whole run fail?**
No. Unrecognisable entries are reported in the log and skipped, and the run continues with the remaining games.

**Is this legal?**
The Actor collects only publicly available data — no login, no private profiles, no personal data beyond the public display names Steam already shows. You are responsible for using the data in line with Steam's terms and applicable law in your jurisdiction.

***

### 📞 Support

Questions, bug reports, or a field you'd like added?

- 📧 **Email:** <me@ahmedhrid.com>
- 💬 **Issues tab** on this Actor's Apify page

When reporting a problem, please include the **run ID** and the **input** you used — it makes diagnosis much faster.

Feature requests are welcome. If you need a field this Actor doesn't return yet, get in touch.

***

### 🔗 Related keywords

Steam review scraper · scrape Steam reviews · Steam data extraction · game review scraping · Apify Actor · web scraping · Steam API alternative · player sentiment analysis · game market research · Steam user reviews export · video game data scraping

# Actor input Schema

## `startUrls` (type: `array`):

Steam store or community URLs, e.g. https://store.steampowered.com/app/292030/ or https://steamcommunity.com/app/292030/reviews/. Leave empty if you are using App IDs instead.

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

Steam numeric App IDs, one per line, e.g. 292030. The App ID is the number in a store URL: store.steampowered.com/app/<APP ID>/. Use this instead of Start URLs, or alongside them — a game listed in both is only scraped once.

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

Maximum number of reviews to scrape per game. 0 means no limit. Steam serves 10 reviews per request, so higher values mean proportionally more requests.

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

Which review ordering to walk. 'Most recent' is the only date-sorted option and the only one where the target date cuts the run short.

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

Language of the reviews to collect. 'default' returns all languages.

## `targetDate` (type: `string`):

Skip reviews posted before this date (ISO 8601, e.g. 2025-01-01). With 'Most recent' this also stops the run early, which makes it useful for incremental runs — set it to the date of your last run.

## `includeGameInfo` (type: `boolean`):

Fetch the store page for the game's name, developer, publisher, release date, price, tags, and overall review summary. Costs one extra request per game.

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

Optional. Steam serves these endpoints without a bot wall, but a proxy helps avoid per-IP rate limiting on long runs.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://store.steampowered.com/app/292030/"
    }
  ],
  "maxReviews": 100,
  "reviewFilter": "toprated",
  "reviewLanguage": "default",
  "includeGameInfo": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `games` (type: `string`):

Dataset with one record per Steam game: name, app ID, reviews URL, review summary, total review count, number of reviews scraped, and the array of review objects.

# 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 = {
    "startUrls": [
        {
            "url": "https://store.steampowered.com/app/292030/"
        }
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("reviewly/stream-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 = {
    "startUrls": [{ "url": "https://store.steampowered.com/app/292030/" }],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("reviewly/stream-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 '{
  "startUrls": [
    {
      "url": "https://store.steampowered.com/app/292030/"
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call reviewly/stream-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,reviewly/stream-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/4nYcQijoFIkAfC1nD/builds/Ty7lkJvkkE5fGMnia/openapi.json
