# Steam Reviews Scraper \[$0.8/1k💰] | WAF Bypass | Sentiment (`ahmed_jasarevic/steam-reviews-cheerio-scraper`) Actor

Scrape Steam game reviews with anti-bot TLS fingerprinting that bypasses Steam's WAF. Dual-mode JSON API + Cheerio fallback with date, language, sentiment, and playtime filters. No API key, no login. Structured output for sentiment analysis, NLP datasets, and game market research.

- **URL**: https://apify.com/ahmed\_jasarevic/steam-reviews-cheerio-scraper.md
- **Developed by:** [Ahmed Jasarevic](https://apify.com/ahmed_jasarevic) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.77 / 1,000 results

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?

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 Scraper — Dual-Mode WAF Bypass + Cheerio Fallback

[![Apify Actor](https://img.shields.io/badge/Apify-Actor-blue)](https://apify.com/ahmed_jasarevic/steam-reviews-cheerio-scraper)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow)](https://opensource.org/licenses/MIT)

Extract **Steam game reviews** at scale using two extraction modes: a high-speed JSON API with TLS fingerprinting (`got-scraping`) that bypasses Steam's Custom WAF, and a Cheerio-based HTML fallback for when API access is blocked. No API key, no login, no cookies. Supports date window filtering, language/sentiment/purchase filters, and playtime-based review quality scoring.

### Main Use Cases

- **Sentiment analysis** — build labeled review corpora (positive/negative) for NLP model training and fine-tuning
- **Game market research** — compare review sentiment, volume, and themes across competing titles
- **Player feedback intelligence** — surface recurring bugs, feature requests, and praise from real player reviews
- **Competitor monitoring** — track rival game review sentiment and complaint trends over time
- **Voice-of-customer datasets** — structured review data for BI dashboards, Tableau, or data warehouses
- **Review bomb detection** — isolate off-topic or coordinated review campaigns using date and purchase filters

### How It Works

#### Mode 1: JSON API (Default — Fastest)

Uses `got-scraping` to hit Steam's public `store.steampowered.com/appreviews/{appid}` endpoint with **Chrome TLS fingerprint impersonation**. This bypasses Steam's Custom WAF that blocks requests with non-browser TLS signatures (JA3/JA4 detection).

```
got-scraping → Steam API → TLS fingerprint bypass → JSON response → Cheerio parse
```

#### Mode 2: HTML/Cheerio (Fallback)

When the API returns 403 or WAF blocks the request, the Actor automatically falls back to `CheerioCrawler` which renders the HTML review page and extracts reviews using CSS selectors.

```
Steam Store HTML → CheerioCrawler → CSS selector extraction → Review objects
```

#### Anti-Bot Bypass Stack

1. **TLS Fingerprinting** — `got-scraping` uses `curl_cffi` to impersonate Chrome 120+ TLS fingerprints, bypassing WAF detection that rejects non-browser TLS
2. **Apify Proxy Rotation** — Residential IPs prevent datacenter IP detection
3. **Complete Headers** — Proper `Sec-Fetch-*`, `Accept`, `Origin`, `Referer` headers
4. **Rate Limiting** — Configurable delays between requests to avoid 429 responses
5. **Exponential Backoff** — Retry logic with increasing wait times on 429/5xx errors
6. **Session Persistence** — Cookie jar maintained across requests

### Input

| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
| `appIds` | array | **Yes** | — | Steam App IDs (e.g. `570`) or store URLs |
| `maxItems` | integer | No | `1000` | Hard cap across every app |
| `language` | string | No | `all` | Steam language code: `english`, `german`, `french`, `spanish`, `russian`, `schinese`, etc. |
| `reviewType` | string | No | `all` | `all`, `positive`, `negative` |
| `purchaseType` | string | No | `all` | `all`, `steam`, `non_steam_purchase` |
| `filter` | string | No | `recent` | `recent`, `updated`, `all` (sorted by helpfulness) |
| `mode` | string | No | `auto` | `api` (fastest), `html` (WAF bypass), `auto` (try API, fallback to HTML) |
| `onlyReviewsAfter` | string | No | — | Start date window (`YYYY-MM-DD`) |
| `onlyReviewsBefore` | string | No | — | End date window (`YYYY-MM-DD`) |
| `includeOffTopic` | boolean | No | `false` | Include review bombs |
| `useReviewQuality` | boolean | No | `true` | Use Steam's helpfulness filter |
| `playtimeFilterMin` | integer | No | `0` | Min playtime in hours |
| `playtimeFilterMax` | integer | No | `0` | Max playtime in hours |
| `numPerPage` | integer | No | `50` | Reviews per API call (1–100) |
| `requestDelayMs` | integer | No | `1000` | Delay between requests |
| `maxRetries` | integer | No | `3` | Retry attempts on errors |
| `proxyConfiguration` | object | No | `{useApifyProxy: true}` | Apify proxy settings |

### Output

Each review row contains:

| Field | Type | Description |
|---|---|---|
| `review_text` | string | Full review body |
| `voted_up` | boolean | Recommendation (true = positive) |
| `votes_helpful` | integer | Helpful vote count |
| `votes_funny` | integer | Funny vote count |
| `weighted_vote_score` | number | Steam's weighted helpfulness score |
| `comment_count` | integer | Comment count |
| `timestamp_created` | integer | Unix timestamp — review creation |
| `timestamp_updated` | integer | Unix timestamp — last edit |
| `author` | string | Username |
| `author_steamid` | string | Steam ID |
| `author_playtime_forever_hours` | number | Total hours played |
| `author_playtime_at_review_hours` | number | Hours played at review time |
| `language` | string | Review language code |
| `steam_purchase` | boolean | Purchased on Steam |
| `received_free` | boolean | Received for free |
| `written_during_early_access` | boolean | Early access flag |
| `steam_deck` | boolean | Played on Steam Deck |
| `app_id` | string | Steam App ID |
| `review_score` | integer | Summary score |
| `review_score_pct` | number | Score percentage |
| `total_positive` | integer | Total positive reviews |
| `total_negative` | integer | Total negative reviews |
| `total_reviews` | integer | Total review count |
| `_metadata` | object | Run metadata: mode used, pages walked, API fallback count |

### Example Input

```json
{
  "appIds": ["570", "292030"],
  "maxItems": 500,
  "language": "english",
  "reviewType": "all",
  "purchaseType": "all",
  "filter": "recent",
  "onlyReviewsAfter": "2025-01-01",
  "onlyReviewsBefore": "2026-01-01",
  "includeOffTopic": false,
  "useReviewQuality": true,
  "playtimeFilterMin": 10,
  "numPerPage": 50,
  "requestDelayMs": 1000,
  "maxRetries": 3,
  "mode": "auto",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

### Example Output

```json
{
  "review_text": "After the patches this is exactly the game I hoped for. 120 hours in and Night City still surprises me.",
  "voted_up": true,
  "votes_helpful": 412,
  "votes_funny": 33,
  "weighted_vote_score": 0.87,
  "comment_count": 5,
  "timestamp_created": 1718390400,
  "timestamp_updated": 1718390400,
  "author": "CyberFan2077",
  "author_steamid": "76561198012345678",
  "author_playtime_forever_hours": 7284,
  "author_playtime_at_review_hours": 6100,
  "language": "english",
  "steam_purchase": true,
  "received_free": false,
  "written_during_early_access": false,
  "steam_deck": false,
  "app_id": "1091500",
  "review_score": 8,
  "review_score_pct": 86.5,
  "total_positive": 642000,
  "total_negative": 101000,
  "total_reviews": 743000,
  "_metadata": {
    "mode": "api",
    "apps_scraped": 2,
    "pages_walked": 10,
    "api_fallback_count": 0,
    "reviews_trimmed": 0,
    "total_reviews": 500,
    "total_summaries": 2,
    "timestamp": "2026-09-11T12:00:00Z"
  }
}
```

### Integrations & Automation

- **Webhooks** — trigger downstream processing (data warehouse loads, Slack alerts) when a run finishes
- **Schedules** — set up daily or weekly scraping to track review sentiment over time around game launches and patches
- **Google Sheets / Airtable** — export dataset directly to spreadsheets for non-technical stakeholders
- **Zapier / Make** — connect review data to CRM, notification, or reporting workflows
- **API** — call this Actor programmatically from any stack via the Apify API with your token

### Related Actors

- [Steam Game Reviews Scraper — Sentiment & Player Data](https://apify.com/logiover/steam-game-reviews-scraper) — broader scope: also pulls game metadata (price, genres, Metacritic) alongside reviews; pay-per-result
- [Steam Reviews Scraper — Pay Per Result](https://apify.com/danek/steam-reviews-ppr) — simpler single-mode scraper focused on download-all volume
- [Steam Game Reviews Scraper — Batch + Search](https://apify.com/automation-lab/steam-game-reviews-scraper) — supports game name search and metadata enrichment; 64 users, 5★ rating
- [Steam Game Reviews Scraper — AI Analysis](https://apify.com/pappy-dev/steam-review-intelligence) — adds AI-powered review bomb detection, pain points, and summary analysis on top of raw reviews

### Frequently Asked Questions

#### Why use this Actor instead of the official Steam API?

Steam's `appreviews` endpoint is publicly accessible, but it has no official SDK, no published rate limits (just undocumented 403/429 blocks), and the TLS fingerprint of standard HTTP clients (Python `requests`, Node `axios`) gets flagged by Steam's Custom WAF. This Actor solves that with `got-scraping` TLS impersonation + CheerioCrawler HTML fallback, so you get consistent results without managing proxy rotation, header spoofing, or retry logic yourself.

#### What are alternatives to this Actor?

For Steam review data, alternatives include the Python `steamreviews` PyPI package (manual, no WAF bypass), the official Steamworks Web API (requires developer key), SteamApis.com (paid API with key), or building your own Scrapy/Cheerio pipeline. On Apify, competitors include [logiover/steam-game-reviews-scraper](https://apify.com/logiover/steam-game-reviews-scraper), [danek/steam-reviews-ppr](https://apify.com/danek/steam-reviews-ppr), and [automation-lab/steam-game-reviews-scraper](https://apify.com/automation-lab/steam-game-reviews-scraper).

#### How do I scrape all reviews for a specific Steam game?

Set `appIds` to the game's numeric App ID (find it in the store URL: `store.steampowered.com/app/{APP_ID}/`). Set `maxItems` high enough to cover the full review count (check the store page for the total), and use `mode: "auto"` for the best balance of speed and reliability.

#### Can I filter reviews by date range?

Yes. Set `onlyReviewsAfter` and `onlyReviewsBefore` to ISO date strings (e.g. `"2025-06-01"`). Only reviews created within that window will be included in the dataset.

#### Does this work without proxies?

The Actor includes Apify Proxy rotation by default. You can disable it by setting `proxyConfiguration: { useApifyProxy: false }`, but Steam's WAF will likely block requests from datacenter IPs without TLS fingerprinting.

#### Can I use this for NLP or sentiment analysis training data?

Yes. The output includes full review text, sentiment labels (`voted_up`), playtime context, helpfulness votes, and language codes — everything you need for labeled sentiment classification datasets.

#### What is the difference between `mode: "api"`, `mode: "html"`, and `mode: "auto"`?

- `api` — forces the JSON API path (fastest, but may get blocked by WAF)
- `html` — forces CheerioCrawler HTML extraction (slower, but more resilient)
- `auto` — tries API first, automatically falls back to HTML on 403/WAF blocks

#### How does playtime filtering work?

Set `playtimeFilterMin` and `playtimeFilterMax` (in hours) to include only reviews from players within that playtime range. Useful for filtering out refund-window reviews (<2h) or isolating hardcore player feedback.

### SEO Keywords

steam reviews scraper, steam game review data, steam review sentiment analysis, steam api alternative, steam reviews api, steam game reviews download, steam review data extraction, steam reviews csv export, steam reviews nlp dataset, steam review text scraping, game review data collection, steam player feedback analysis, steam reviews by app id, steam reviews without api key, steam review monitoring, steam game sentiment tracking, steam reviews for machine learning, steam review corpus, steam review text analysis, steam reviews api bypass, got-scraping steam, tls fingerprinting steam, cheerio crawler steam reviews, steam review data pipeline

### For AI Agents & LLM Apps

**Purpose:** Extract structured Steam game review data (review text, sentiment, playtime, helpfulness votes, timestamps, language) for any game by Steam App ID. Dual-mode: fast JSON API with TLS fingerprinting + Cheerio HTML fallback.

**Minimal input:**

```json
{ "appIds": ["570"], "maxItems": 100 }
```

**With filters:**

```json
{ "appIds": ["730"], "language": "english", "reviewType": "negative", "maxItems": 500, "onlyReviewsAfter": "2025-01-01" }
```

**Output fields:** `review_text`, `voted_up`, `votes_helpful`, `votes_funny`, `weighted_vote_score`, `comment_count`, `timestamp_created`, `timestamp_updated`, `author`, `author_steamid`, `author_playtime_forever_hours`, `author_playtime_at_review_hours`, `language`, `steam_purchase`, `received_free`, `written_during_early_access`, `steam_deck`, `app_id`, `review_score`, `review_score_pct`, `total_positive`, `total_negative`, `total_reviews`, `_metadata`

**Non-obvious behaviors:**

- `mode: "auto"` (default) tries API first; falls back to HTML on 403 — use `mode: "api"` for speed when WAF isn't blocking, `mode: "html"` when consistently blocked
- `requestDelayMs` defaults to 1000ms — lowering it increases speed but raises 429 risk
- `includeOffTopic: true` adds review-bomb reviews; default `false` excludes them
- `useReviewQuality: true` filters out low-helpfulness reviews
- `playtimeFilterMin/Max` are in hours, not minutes
- Reviews outside the `onlyReviewsAfter`/`onlyReviewsBefore` window are filtered before being pushed to dataset (not billed)

**Pricing:** Pay-per-event — $0.00005 per actor start + $0.0008 per review result. No charges for filtered-out reviews.

### Legal & Compliance Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Valve Corporation or the Steam platform. It accesses only publicly available Steam Store pages and API endpoints — no login bypass, no private API access, no CAPTCHA solving. Users are responsible for their own compliance with Steam's Terms of Service and applicable data-protection laws (including GDPR/CCPA where review data may contain personal information). Do not use scraped review data for unsolicited commercial outreach in violation of applicable law (e.g. CAN-SPAM, GDPR, TCPA).

# Actor input Schema

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

Numeric Steam app IDs or Steam store URLs

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

Hard cap across every app

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

Steam language code

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

Filter by recommendation

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

Where the copy came from

## `filter` (type: `string`):

How to sort reviews

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

api, html, or auto

## `onlyReviewsAfter` (type: `string`):

Start date window (YYYY-MM-DD)

## `onlyReviewsBefore` (type: `string`):

End date window (YYYY-MM-DD)

## `includeOffTopic` (type: `boolean`):

Include review bombs

## `useReviewQuality` (type: `boolean`):

Use helpfulness filter

## `playtimeFilterMin` (type: `integer`):

Minimum playtime filter

## `playtimeFilterMax` (type: `integer`):

Maximum playtime filter

## `numPerPage` (type: `integer`):

Reviews per API call

## `requestDelayMs` (type: `integer`):

Delay between requests

## `maxRetries` (type: `integer`):

Retry attempts

## Actor input object example

```json
{
  "appIds": [
    {
      "url": "https://store.steampowered.com/app/570/"
    }
  ],
  "maxItems": 10,
  "language": "all",
  "reviewType": "all",
  "purchaseType": "all",
  "filter": "recent",
  "mode": "auto",
  "includeOffTopic": false,
  "useReviewQuality": true,
  "playtimeFilterMin": 0,
  "playtimeFilterMax": 0,
  "numPerPage": 50,
  "requestDelayMs": 1000,
  "maxRetries": 3
}
```

# Actor output Schema

## `dataset` (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": [
        {
            "url": "https://store.steampowered.com/app/570/"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ahmed_jasarevic/steam-reviews-cheerio-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": [{ "url": "https://store.steampowered.com/app/570/" }] }

# Run the Actor and wait for it to finish
run = client.actor("ahmed_jasarevic/steam-reviews-cheerio-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": [
    {
      "url": "https://store.steampowered.com/app/570/"
    }
  ]
}' |
apify call ahmed_jasarevic/steam-reviews-cheerio-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ahmed_jasarevic/steam-reviews-cheerio-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/RVI30RBPTGcRsiO3X/builds/xukdw5FIf3M9iAgfz/openapi.json
