Steam Game Data API — Prices, Players & Charts
Pricing
from $0.72 / 1,000 game profile returneds
Steam Game Data API — Prices, Players & Charts
Scrape Steam as data. One row per game: price, discount, release date, developer, genres, tags, Metacritic, live player count, owner estimates and the review score. Plus the Most Played and Top Sellers charts, Specials, and store search by keyword or tag. No API key, no login.
Pricing
from $0.72 / 1,000 game profile returneds
Rating
0.0
(0)
Developer
Insight Solutions
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
9 days ago
Last modified
Categories
Share
Steam Game Data API — Prices & Players
Every number Steam publishes about a game, as a flat table. Give this Actor an app ID, a store link or just a game's name — mixed together, in any order — and get one row per game: the current price and discount in any storefront's currency, the release date, developer and publisher, genres and community tags, the Metacritic score, how many people are playing right now, owner estimates, and the review score. Add a chart name and you get Valve's Most Played top 100 or the store's Top Sellers; add a keyword or a tag and you get the store's own search results, 50 to a page.
A Steam game data API, a Steam player count feed and a Steam top sellers scraper in one Actor. No API key. No login. No Steam account. $1.20 per 1,000 games, proxy included, charts and search results are $0.30 per 1,000, games that could not be read are free, and a run that returns nothing costs nothing at all.
Try it in 30 seconds
{"apps": ["570", "Elden Ring", "https://store.steampowered.com/app/413150/Stardew_Valley/"],"charts": ["most-played"],"chartSize": 25,"country": "us"}
Three games and the live top 25. A bare ID (570), a store link and the plain name Elden Ring all reach the same place — the name costs one extra request and the row says resolvedFrom: "name" so you can see a guess was made.
Want the market rather than three games? {"charts": ["top-sellers", "specials"], "chartSize": 100}. Want a list? {"searchQueries": ["souls"], "tagIds": ["4026"], "sortBy": "released", "maxResultsPerQuery": 500}.
Output — one row per game, plus one per chart position and per search hit; the fields you will use most are appId, name, price, discountPercent, currentPlayers and reviewScoreDesc (full list under Output reference). Anything that could not be read comes back as a free diagnostic row (ok: false, errorType, error) instead of a charge.
Price — $1.20 per 1,000 games on the FREE tier, $0.30 per 1,000 chart entries and search results, plus $0.001 per run; games that do not exist, searches that matched nothing, blocked requests and every diagnostic row are free, and a run that returns nothing bills nothing at all. Pay-per-event, no API key, no browser, limited permissions — it works over the Apify MCP server (mcp.apify.com) and with agentic (x402) payments.
From code — client.actor("insight.solutions/steam-store-stats-api").call(run_input={…}) with apify-client, or POST https://api.apify.com/v2/acts/insight.solutions~steam-store-stats-api/run-sync-get-dataset-items. Full snippets under Use it from an AI agent, or from code.
What comes back
One game row per app:
{"ok": true,"rowType": "game", // "game" | "chart-entry" | "search-result" | "diagnostic""appId": "570", // the join key across every row of this game"name": "Dota 2","type": "game", // "game" | "dlc" | "demo" | "music" | "video" | "hardware""storeUrl": "https://store.steampowered.com/app/570/","resolvedFrom": "app-id", // "app-id" | "name" | "chart" | "search""isFree": true,"price": 0, // in `currency`, after any discount. Free is 0, not null"initialPrice": 0, // list price before the discount"discountPercent": 0,"currency": null, // "USD", "EUR", … — a free game carries no price block"priceFormatted": null, // "59,99€" — exactly as Steam renders it"releaseDate": "2013-07-09", // ISO, when Steam gave an actual day"releaseDateText": "Jul 9, 2013", // Steam's own string: "24 Feb, 2022", "Q2 2027", "To be announced""comingSoon": false,"developers": ["Valve"],"publishers": ["Valve"],"genres": ["Action", "Strategy", "Free To Play"],"categories": ["Multi-player", "Co-op", "Steam Trading Cards", "Steam Workshop"],"tags": ["Free to Play", "MOBA", "Multiplayer", "Strategy", "e-sports"], // community tags, by votes"tagVotes": { "Free to Play": 60040, "MOBA": 20225 },"platforms": ["windows", "mac", "linux"],"supportedLanguages": ["Bulgarian", "Czech", "English*", "Korean*"], // * = full audio"metacriticScore": 90,"achievementCount": 0,"dlcCount": 2,"dlcAppIds": ["1241930", "652720"], // feed these back in to price a whole catalogue"requiredAge": 0,"controllerSupport": null,"currentPlayers": 651234, // in the game at this instant, from Valve's own endpoint"ccuYesterday": 623941, // yesterday's peak, from SteamSpy"ownersMin": 100000000, // SteamSpy ESTIMATE — a sampled range, not a Valve figure"ownersMax": 200000000,"averagePlaytimeMin": 0, // SteamSpy estimate, minutes; 0 where it publishes none"medianPlaytimeMin": 0,"reviewScoreDesc": "Very Positive","reviewScore": 8, // Steam's internal 0–9 score behind that wording"totalReviews": 2776617,"positiveReviews": 2235327,"negativeReviews": 541290,"positiveRatio": 80.5,"country": "us","scrapedAt": "2026-09-11T23:05:24.794Z","source": "steam-store", // "steam-store" | "steam-api" | "steamspy""sourceUrl": "https://store.steampowered.com/app/570/"}
One chart-entry row per chart position:
{"ok": true,"rowType": "chart-entry","chart": "most-played","chartPeriod": "2026-09-10T00:00:00.000Z", // the month's name on "top-releases""rank": 1,"appId": "730","name": "Counter-Strike: Global Offensive","peakInGame": 1259987, // Valve's peak for the chart period"lastWeekRank": 1, // the movement column, free with the chart"price": 0, "discountPercent": 0, "currency": "USD","ownersMin": null, // populated on the SteamSpy chart"storeUrl": "https://store.steampowered.com/app/730/"}
And one search-result row per hit:
{"ok": true,"rowType": "search-result","query": "souls","position": 1,"appId": "677790","name": "SOULS","itemType": "app", // "app" | "package" | "bundle""price": 7.99, "initialPrice": 7.99, "discountPercent": 0, "currency": "USD","releaseDateText": "Aug 14, 2017","reviewScoreDesc": "Very Positive","positiveRatio": 88,"totalReviews": 124,"platforms": ["windows"],"tagIds": [3799, 1742, 7250, 4085], // the same numbers the `tagIds` input takes"storeUrl": "https://store.steampowered.com/app/677790/SOULS/"}
Every row carries the same columns, so games, charts, searches and diagnostics export as one rectangular table.
Use cases
- Price and discount monitoring. A scheduled run over a few hundred app IDs gives you
price,initialPriceanddiscountPercentper storefront, every day, for a fraction of a cent per game. Run the same list withcountry: "us","de"and"br"and you have regional pricing in one sheet. - Sale detection.
{"charts": ["specials"], "chartSize": 100}is one request. Diff it against yesterday and you know what went on sale this morning. - Chart tracking. As a Steam top sellers scraper it returns
top-sellersandglobal-top-sellersup to 500 deep;most-playedcarriesrank,peakInGameandlastWeekRank, so a single daily run is already a time series with its own movement column. - Market and competitor research.
searchQuerieswithtagIdsandsortBy: "released"returns up to 500 rows per query: every game in a genre, with price, review score and release date. That is a market map, not a page of search results. - Wishlist and catalogue enrichment. Feed a list of app IDs from anywhere — a wishlist export, a bundle, a spreadsheet — and get names, prices, genres, platforms and review scores back in one pass.
- Live player-count dashboards.
currentPlayersis Valve's own Steam player count for that instant. Poll a list of games hourly and you have concurrency curves without a single scraped web page. - Game discovery and LLM pipelines. Name, short description, genres, community tags and review score as a flat array is a labelled corpus for recommendation work — and
tagIdson every search row feeds straight back into the next query.
How it works, and why it keeps working
There is no Steam API for this, because Steam's store is not an API — it is a shop with a JSON endpoint behind each of its own widgets. This Actor reads eight of them and merges the results.
| Source | What it reads | Shape |
|---|---|---|
| Store page | store.steampowered.com/api/appdetails?appids=…&cc=… | JSON. Price, genres, categories, platforms, Metacritic, DLC, languages |
| Live players | api.steampowered.com/ISteamUserStats/GetNumberOfCurrentPlayers/v1/ | JSON. One number: who is in the game right now |
| Most played | api.steampowered.com/ISteamChartsService/GetMostPlayedGames/v1/ | JSON. Valve's live top 100 — ranks, peaks, last week's position |
| Top releases | api.steampowered.com/ISteamChartsService/GetTopReleasesPages/v1/ | JSON. The newest three monthly lists |
| Store search | store.steampowered.com/search/results/?…&infinite=1 | JSON wrapping HTML: 50 result rows a page |
| Search box | store.steampowered.com/search/suggest?term=… | HTML. Turns a game's name into an app ID |
| Front page | store.steampowered.com/api/featuredcategories | JSON. Specials, new releases, coming soon, top sellers |
| Review score | store.steampowered.com/appreviews/<id>?num_per_page=0 | JSON. The totals, without any of the reviews |
| SteamSpy (opt-in, on by default) | steamspy.com/api.php?request=appdetails | JSON. Owner and playtime estimates, plus community tags |
Four things catch naive scrapers here, and all four are handled:
Valve's charts have no names in them. GetMostPlayedGames returns a hundred bare app IDs, and Steam has no batched name lookup (a multi-id appdetails call only accepts the price filter — checked live). So this Actor reuses any names it already learned from SteamSpy's chart in the same run and looks the rest up one appdetails request per app — capped at the chart size you asked for, and with a log line saying how many it resolved. Prices for chart rows are fetched in batches of 100.
Steam's store search is HTML pretending to be JSON. The response is {success, results_html, total_count, start}, where results_html is 110 KB of markup. The parser here reads the attributes off each row — data-ds-appid, data-ds-tagids, data-price-final, the review tooltip — with no DOM library, in about 3 ms a page. It handles the awkward cases the captures contain: free items, discounts with a struck-through original price, rows with no review summary at all (39 of 50 on one captured page), unreleased titles whose "date" is "Q2 2027", and rows where the two price attributes disagree — on the captured Steam Deck listing the wrapper says 39900 and the block that actually renders says 78900.
Prices are per storefront, and the currency is not always stated. appdetails and the front-page sections say what currency they are quoting. Store search does not: it renders "59,99€" and nothing machine-readable. country therefore drives both the request and the currency label, and the row keeps Steam's rendered string in priceFormatted so you can check.
SteamSpy is a volunteer service. It asks for one request a second, and this Actor gives it exactly that — every SteamSpy call in the run queues through a single gate, whatever maxConcurrency is set to. A SteamSpy outage leaves its columns null and is logged; it never fails a row, because a Steam game is worth returning without an owner estimate.
Underneath: Apify datacenter proxy by default, one pinned session per parallel worker. Every endpoint above answered a datacenter address in the captures, which is why residential is not the default and why the proxy cost is already inside the per-row price. When an endpoint refuses an exit IP — HTTP 429, HTTP 403, an empty body, HTML where JSON belongs, or a proxy-side "Access denied" page — that session is retired and the same request goes out once more from a different address. Retrying on an address that was just refused only deepens the block, so it is never done. If the second address is refused too, the job stops, keeps every row it already delivered, and files one free blocked row saying where it stopped. Requests within one job are spaced 250–600 ms apart.
How it compares
- One schema for games, charts and search. A chart position, a search hit and a game you asked for by ID all produce the same columns, so mixing them is a filter rather than a reconciliation project.
appIdjoins them. - Honest about which numbers are estimates.
currentPlayersis Valve's.ownersMin/ownersMaxare SteamSpy's, they are a range on purpose, and this README says so in three places rather than presenting a midpoint as a fact. - Failures are free and legible. A game that does not exist, an entry that was not a Steam app, an empty search or a block produce a diagnostic row with an
errorTypeyou can branch on — and no charge. A run that returns nothing at all finishes SUCCEEDED with zero results, a status message that says so, and a free diagnostic row per entry telling you why; it finishes FAILED only when no entry was usable, or the Actor itself hit an error. - A partial run is kept, not thrown away. Hit
maxRunSecsor your charge ceiling halfway through a 500-row chart and you keep the ranks already written. - No login, ever. No Steam account, no cookie jar, no session token, no API key belonging to anyone. Public endpoints only, which is also why it runs under Apify's limited permissions.
- Reviews are a separate tool, on purpose. This Actor returns the review score; it never fetches individual reviews. For review text, playtime at review, helpful votes and developer responses, use the companion Steam Reviews API — same input formats, same game row, so the two join on
appId.
Input reference
| Field | Type | Default | What it does |
|---|---|---|---|
apps | array of strings | prefilled with three | App IDs, store links or game names. An age-check or community link resolves to the same app. A name costs one extra request and is flagged resolvedFrom: name. DLC, demos and soundtracks work too — the row's type says which. Duplicates are read, and billed, once |
charts | array (multi-select) | ["most-played"] | most-played, top-sellers, global-top-sellers, new-releases, specials, coming-soon, top-releases, steamspy-top-2weeks. The search-backed ones page 50 at a time; specials, new-releases and coming-soon are the store's front-page sections and already carry names and both prices |
chartSize | integer | 50 | How deep each chart goes. 100 max for most-played and SteamSpy, 500 for the search-backed charts, and whatever the section holds for the front-page ones |
searchQueries | array of strings | [] | Store search by keyword. One search-result row per hit, 50 to a page |
sortBy | relevance | released | name | price-asc | price-desc | reviews | relevance | The order the store returns hits in |
tagIds | array of strings | [] | Restrict searches to Steam tags by numeric ID. Two IDs means both. See the table below |
maxResultsPerQuery | integer | 50 | Hits per query, up to 500 |
onlyGames | boolean | true | Leave DLC, soundtracks, software, hardware and bundles out of searches and search-backed charts |
country | string | us | Two-letter storefront. Drives price, currency, availability and age rating. Not SteamSpy, which is global |
language | string | en | Steam's l parameter — the language of descriptions, genres and categories |
includePlayerCount | boolean | true | Add currentPlayers. One extra request per game |
includeSteamSpy | boolean | true | Add owner and playtime estimates and community tags. One extra request per game, rate-limited to one a second run-wide |
includeReviewSummary | boolean | true | Add the review score and totals. One extra, very cheap, request per game |
enrichChartEntries | boolean | false | Also build a full game row for every chart and search hit. Up to four requests per app — an enriched Top 100 is around 400 requests |
maxConcurrency | integer | 3 | Games, charts or queries in parallel. Each worker keeps its own proxy session |
maxRunSecs | integer | 240 | Whole-run wall-clock budget. When it runs out the Actor keeps what it has and files a free diagnostic row for each entry it never reached |
proxyConfiguration | object | Apify datacenter | Steam answers datacenter addresses happily, so the cheap proxy is the default |
The 50 Steam tag IDs you will actually use
| ID | Tag | ID | Tag | ID | Tag |
|---|---|---|---|---|---|
19 | Action | 1695 | Open World | 1667 | Horror |
21 | Adventure | 1663 | FPS | 1662 | Survival Horror |
122 | RPG | 1774 | Shooter | 1742 | Survival |
492 | Indie | 1625 | Platformer | 4295 | Sandbox |
599 | Simulation | 1698 | Puzzle | 4747 | Base Building |
9 | Strategy | 3798 | Point & Click | 3871 | Crafting |
597 | Casual | 4026 | Souls-like | 4166 | City Builder |
128 | Massively Multiplayer | 1716 | Roguelike | 1654 | Management |
701 | Sports | 1773 | Roguelite | 1755 | Turn-Based Strategy |
699 | Racing | 3839 | Metroidvania | 4325 | Turn-Based Tactics |
3859 | Multiplayer | 4345 | Hack and Slash | 4604 | Fantasy |
4182 | Singleplayer | 4085 | Pixel Graphics | 3942 | Sci-fi |
1685 | Co-op | 4136 | 2D | 1697 | Anime |
3843 | Online Co-Op | 4191 | Story Rich | 4305 | Cute |
3841 | Local Co-Op | 4231 | Atmospheric | 4106 | Relaxing |
1775 | PvP | 1720 | Difficult | 4172 | Free to Play |
3814 | Team-Based | 1719 | Early Access |
Every search-result and chart row carries tagIds, so a result can be turned straight into the next query. The full list lives at steamdb.info/tags.
Output reference
| Column | On which rows | What it is |
|---|---|---|
ok, rowType | all | true plus game / chart-entry / search-result, or false plus diagnostic |
input, query | all | The entry this row came from, as you supplied it; the search query on a search row |
appId | all | Steam's app ID — the join key between every row of one game |
name, type, itemType | all | The game's name; what Steam says it is (game/dlc/demo/…); app, package or bundle |
storeUrl, headerImage, website | most | The store page, the capsule art, the publisher's own site |
price, initialPrice, discountPercent, currency, priceFormatted, isFree | all but diagnostics | Today's price, the list price, the discount, and Steam's own rendering of it |
releaseDate, releaseDateText, comingSoon | all but diagnostics | An ISO date when Steam gave a real day; Steam's own string either way |
developers, publishers, genres, categories | game | Who made it, who sells it, and Steam's own classifications |
tags, tagVotes | game | Community tags by vote count, from SteamSpy, capped at 20 |
tagIds | chart, search | Steam's numeric tag IDs — the same numbers the tagIds input takes |
platforms, supportedLanguages, controllerSupport, requiredAge | game | Windows/Mac/Linux, interface languages (* = full audio), controller support, age gate |
metacriticScore, metacriticUrl, recommendations | game | The critic score, its source page, and Steam's own recommendation count |
achievementCount, dlcCount, dlcAppIds, fullGameAppId | game | Achievements; the DLC catalogue; on a DLC row, the base game |
shortDescription, contentDescriptors | game | The store blurb, and the publisher's mature-content note |
currentPlayers | game | How many people are in the game right now, from Valve |
peakInGame, lastWeekRank | chart | Valve's peak for the period, and where the game ranked a week ago |
ownersMin, ownersMax, averagePlaytimeMin, medianPlaytimeMin, ccuYesterday | game, SteamSpy chart | SteamSpy estimates. Read the owner figures as one range |
reviewScore, reviewScoreDesc, positiveReviews, negativeReviews, totalReviews, positiveRatio | all but diagnostics | The review score. On chart and search rows these come from the store's own row tooltip and are language-filtered |
rank, chart, chartPeriod | chart | Position, which chart, and when it was computed |
position | search | 1-based rank within the query, counting across pages |
resolvedFrom, source, sourceUrl | all | How the app was identified, which upstream the row came from, and the exact address |
error, errorType | diagnostic | What went wrong, and a type to branch on |
country, language, scrapedAt | all | Storefront, language, and when the row was written |
errorType is one of not-found, no-results, blocked, timeout, invalid-input, or unavailable for anything unexpected.
Pricing
$1.20 per 1,000 games. Chart entries and search results are $0.30 per 1,000. Pay-per-event, with proxy already inside those numbers — there is no separate proxy line on your bill for this Actor.
| Event | What triggers it | FREE | Starter | Scale | Business |
|---|---|---|---|---|---|
| Game analysed (primary) | One game row — up to four requests' worth of data | $0.0012 | $0.0012 | $0.00096 | $0.00072 |
| Chart entry returned | One position in one Steam chart | $0.0003 | $0.0003 | $0.0003 | $0.0003 |
| Search result returned | One store-search hit | $0.0003 | $0.0003 | $0.0003 | $0.0003 |
| Run started | Once per run, after the first paid row | $0.001 | $0.001 | $0.001 | $0.001 |
Worked example. 100 games with every enrichment on, plus the Most Played top 100:
- 100 games × $0.0012 = $0.12
- 100 chart entries × $0.0003 = $0.03
- 1 run start = $0.001
- Total: $0.151, from about 403 requests
Price-monitoring example. 500 app IDs, prices only (includePlayerCount, includeSteamSpy and includeReviewSummary all off): 500 × $0.0012 + $0.001 = $0.601 per run, from 500 requests — about $18 a month run daily.
Chart-tracking example. most-played plus specials plus top-sellers at 100 each, no enrichment: 300 × $0.0003 + $0.001 = $0.091 per run, about $2.73 a month run daily, from about a dozen requests.
Market-map example. One tag, sorted by release date, 500 results: 500 × $0.0003 + $0.001 = $0.151, from ten requests.
What you are never charged for: a game that does not exist, an entry that was not a Steam app, a search that matched nothing, a chart position the run never reached before maxRunSecs, or a request the endpoint blocked. A run whose entries were all usable but produced nothing — an app ID that does not exist, a search with no matches, a request the endpoint blocked — finishes SUCCEEDED with zero results, a status message that says so, and a free diagnostic row per entry telling you why; it bills nothing at all, start fee included. A run finishes FAILED only when there was nothing usable to attempt, or the Actor itself hit an error.
Set ACTOR_MAX_TOTAL_CHARGE_USD on a run and the Actor stops fetching once the ceiling is in sight, rather than handing you rows it cannot bill or billing you for rows it cannot hand over. It finishes SUCCEEDED with the ceiling named in its status message, and everything already delivered is yours.
Limits, and the ones that might bite
Owner counts are SteamSpy estimates, not Valve's numbers. Valve has never published owner counts. SteamSpy estimates them by sampling public Steam profiles, and it publishes the result as a band — "100,000,000 .. 200,000,000" — precisely because the middle of that band is not a measurement. This Actor keeps both ends (ownersMin, ownersMax) and never averages them. The same applies to averagePlaytimeMin, medianPlaytimeMin and ccuYesterday: all SteamSpy, all estimates. currentPlayers is the exception — that one is Valve's own live figure. Any tool that gives you a single confident owner number for an arbitrary game is showing you the midpoint of this same range without saying so.
SteamSpy sets the pace of a large run. Its published rate is one request a second and this Actor honours it run-wide, so 1,000 games with includeSteamSpy on is at least 1,000 seconds. Turn it off for big price-monitoring runs; the store data comes back as fast as the proxy allows.
SteamSpy also reports zeros. average_forever and average_2weeks are 0 for every game in the captured top-100 — SteamSpy stopped publishing playtime for many titles when Valve changed what profiles expose. A zero there means "not published", and it is passed through as it arrives rather than converted to null, because SteamSpy really does say 0.
currentPlayers is a snapshot. It is the number at the instant the row was written, not an average or a daily peak. For a peak, ccuYesterday (SteamSpy) and peakInGame (on the most-played chart) are the fields to use. There is no historical player data on any of these endpoints — each run captures the present.
No individual reviews. This Actor returns the review score and the totals. Review text, playtime at review, helpful and funny votes, author profiles and developer responses are the companion Steam Reviews API's job, and it takes the same inputs so the two join on appId.
Prices are per storefront and the storefront is not a translation. country: "de" does not mean "the German price of the US catalogue" — it means the German store, which lists a different set of games, applies different age ratings and prices in EUR. A game that is not sold in a country gets a not-found row for that country, which is correct rather than a bug.
Chart depth is the upstream's, not ours. most-played is exactly 100 entries because that is what Valve publishes. specials, coming-soon and top-sellers from the front page are 10 each and new-releases is 30 — those are the sections' real sizes. Only the search-backed charts go deeper, to 500.
Chart names cost a request each. Valve's most-played and top-releases carry app IDs and nothing else, and Steam offers no batched name lookup, so a 100-row chart is about 100 quick appdetails requests (≈ 30 s). A name that could not be resolved — usually a delisted app — is null and the app ID is still on the row.
Search results are the store's ranking, not a database query. sortBy and tagIds are passed to Steam's own search, and what comes back is what its own front-end would show a shopper — including its relevance model, its regional availability rules and its onlyGames filter. total_count on a busy chart moves between pages; paging past the end returns an empty page rather than an error, and the Actor stops there.
resolvedFrom: "name" means a guess was made. A name is resolved to Steam's first search suggestion. For a distinctive title that is right; for "Souls" it is a coin toss, and pasting the store link removes the ambiguity. The column is there so you can spot it.
The upstream format may change. Steam's store endpoints are the ones its own front-end calls, and none of them is documented or versioned — that is true of every tool that reads this data, including the ones that do not say so. The store-search parser in particular reads an HTML fragment Valve is free to restyle. When a shape changes, rows stop arriving and you get free blocked or no-results diagnostic rows rather than quietly wrong data, and a run that returns nothing bills nothing.
Rate and reliability. Requests go out through proxy sessions pinned per worker, one rotation per block, and a 250–600 ms pause between requests of the same job. Three jobs in parallel is the default; raising maxConcurrency speeds a long list up, and SteamSpy stays at one request a second regardless.
Use it from an AI agent, or from code
One JSON object in, one flat array out — the shape agent runtimes want. The Actor runs with limited permissions, uses pay-per-event pricing and never enters Standby, so it works over the Apify MCP server and with x402 agentic payments. The Integrations tab pushes results to Slack, a webhook, Zapier, Make, Google Sheets, Snowflake or BigQuery.
curl -X POST "https://api.apify.com/v2/acts/insight.solutions~steam-store-stats-api/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"apps":["570","1245620"],"charts":["most-played"],"chartSize":25}'
# pip install apify-clientfrom apify_client import ApifyClientclient = ApifyClient("<APIFY_TOKEN>")run = client.actor("insight.solutions/steam-store-stats-api").call(run_input={"apps": ["Elden Ring", "570"],"charts": ["top-sellers"],"chartSize": 100,"country": "de",})for row in client.dataset(run["defaultDatasetId"]).iterate_items():if row["rowType"] == "game":print(row["name"], row["price"], row["currency"], row["currentPlayers"])
FAQ
Do I need a Steam account or an API key? No. Every source here is public: the store's own JSON endpoints, Valve's public Web API charts, and SteamSpy. The Actor never logs in and never accepts a cookie or session token.
How do I deduplicate between runs?
On appId. An incremental price history is an append keyed on (appId, country, scrapedAt); a catalogue is an upsert on (appId, country).
Can I get a game's price in several currencies at once?
Run it once per country. Each run's rows carry their own country and currency, so they stack into one table.
Why is currency null on a free game?
Because Steam sends no price block at all for one. price is 0 and isFree is true, which together say everything the missing currency would have.
Why did a chart row come back with no name?
Valve's most-played and top-releases charts contain app IDs only. The Actor resolves names from SteamSpy's chart when it is in the same run and otherwise one appdetails request per app; if that fails for an app — usually one that has been delisted — the row keeps the rank and the ID.
Why is totalReviews smaller on a search row than on the game row?
They come from different places. The game row's figure is every review in every language, from the review endpoint. The search row's is the count Steam prints in its own tooltip, which is filtered to the languages the storefront serves.
What does enrichChartEntries cost?
Up to four requests per app, and each resulting row is billed as a game. An enriched Top 100 is about 400 requests and $0.15. The chart rows alone are $0.03. It is off by default for that reason.
Can I search without a keyword?
Yes — leave searchQueries with an empty string or use the top-sellers chart, and set tagIds. That browses a tag rather than searching for words.
What happens if one game fails?
The others still run. The failed one produces a free diagnostic row and the run finishes SUCCEEDED. If every entry fails, the run still finishes SUCCEEDED, with zero results, a status message that says so and one diagnostic row per entry, and you are billed nothing at all. It finishes FAILED only when nothing you sent could be read as an app, a chart name or a search query, or the Actor itself hit an error.
Is the data fresh? Live. Every run reads Steam at that moment; nothing is cached. SteamSpy's own figures are as fresh as SteamSpy's last sample, which is its business, not ours.
Legal and data-protection notes
- Public endpoints only. Every address this Actor reads is one Steam's own store front-end calls, unauthenticated, from a browser. It never logs in, never accepts cookies or session tokens, and never uses an API key belonging to anyone.
- No personal data. This Actor returns facts about products: prices, genres, player counts, aggregate review scores. It reads no user profiles, no reviews, no author names and no Steam IDs. The companion reviews Actor handles review authors and has its own notes on that.
- SteamSpy's numbers are a third party's estimates. Owner and playtime figures come from SteamSpy, not from Valve, and they are estimates derived from sampled public profiles. Attribute them accordingly if you republish them, and do not present the middle of an owner band as a measurement.
- Store content belongs to its publisher. Names, descriptions, capsule art and screenshots are copyrighted works. Indexing, price comparison, analysis and linking are the ordinary uses and are what this is built for; republishing artwork or descriptions is your call and your responsibility.
- Not affiliated with Valve Corporation, with SteamSpy, or with any game, developer or publisher whose data you retrieve. Steam is a trademark of Valve Corporation. All names and trademarks belong to their owners and are used only to describe which public endpoints this Actor reads.
Our other Actors
Every Insight Solutions Actor is pay-per-result with no browser, no login and no API key, and every one of them returns free diagnostic rows instead of billing for failures. Prices are per 1,000 results.
Video, audio & social
- YouTube Transcript API — captions as timed segments, text, SRT or VTT, with language fallback and translation.
- YouTube Comments API — comments and replies with likes, pinned and hearted flags, newest or top sort.
- YouTube Channel API — a channel's videos, Shorts and live streams, plus YouTube search.
- Podcast Search, Episodes & Charts API — Apple Podcasts search, charts and full episode feeds.
- Bluesky Scraper — profiles, posts, followers and follows from the public AT Protocol API.
- Telegram Channel Scraper — posts, views and channel stats from public Telegram channels.
- Substack Scraper — posts with full free text, comments and publication profiles.
- Hacker News API — stories, comments, users, front page and a structured "Who is hiring?" parser from the official HN APIs.
- GitHub Repos, Trending & Releases API — repository facts, trending lists, releases and search, no token needed for small runs.
- Discourse Forum API — topics, posts and categories from any Discourse community via its own JSON endpoints, usernames only.
News, documents & the web
- Google News Search, Topics & Real Article URLs — news search and topic feeds with the publisher's real URL decoded.
- Website to Markdown — Content Extractor for LLMs & RAG — any site as clean Markdown, text and heading-aware chunks.
- WordPress Posts & Pages API — posts and pages from any WordPress site as clean text or Markdown, with categories, tags and images.
- Website Metadata API — any URL's meta tags, Open Graph, Twitter cards, hreflang, feeds, JSON-LD and microdata, with normalised Product, Article, Event and FAQ entities.
- Subdomain Finder API — every subdomain of a domain from certificate-transparency logs, resolved over DNS, with an optional live HTTP check.
- Internet Archive API — archive.org search, item metadata, files and reviews.
- Wayback Machine Toolkit — archived URL inventories, snapshots and text diffs between dates.
- Website Technology Detector — the tech stack behind any site, with the evidence for each detection.
- Domain Intelligence API — DNS, RDAP registration, TLS certificate and HTTP facts in one row per domain.
- SEO Page Audit — sitemap crawl with on-page checks, structured data and broken-link reports.
- Keyword Suggestions API — Google, YouTube, Bing, Amazon and eBay autocomplete with alphabet and question expansions.
- Website Contact Extractor — emails, phone numbers and social profiles from any list of websites.
- Web Search Results API — Bing and DuckDuckGo organic results with snippets, no key, no browser.
- Company Enrichment API — a domain in, a company profile out: firmographics, contacts, tech stack, DNS and hiring signal.
- Company Dossier API — one company in, twelve sections out: profile, tech, contacts, DNS, open roles, news, SEC filings, federal awards, recalls, YC batch and apps.
- Press Releases API — GlobeNewswire and PR Newswire releases plus any newsroom feed, by keyword, company, ticker or subject.
- Federal Register API — rules, proposed rules, notices and the Public Inspection desk with dockets, comment deadlines and CFR references.
- Academic Papers Search API — OpenAlex, Crossref, arXiv and PubMed in one row per paper: abstract, citations, open-access PDF, authors and venue.
- RSS & Atom Feed Monitor — any RSS, Atom or JSON feed (or an OPML file) in, only the new items out, with keyword filters and a webhook.
- Website Change Monitor — watch any pages, diff the text between runs, get change rows with added/removed lines, keyword alerts and a webhook.
- Wikipedia & Wikidata API — article text, search, daily pageviews and Wikidata entity facts, any language edition.
Business, finance & jobs
- Congress & Insider Trades API — STOCK Act periodic transaction reports and SEC Form 4 insider trades in one schema.
- Federal Contracts, Grants & Lobbying API — SAM.gov opportunities, USAspending awards, Grants.gov notices and Senate lobbying filings in one schema.
- SEC EDGAR API — filings, XBRL financials and full-text search by ticker or CIK.
- Clinical Trials & FDA API — ClinicalTrials.gov studies plus openFDA recalls, labels, approvals, 510(k)s and adverse-event reports.
- Product & Vehicle Recalls API — CPSC, NHTSA, FDA and USDA recalls, vehicle complaints and ratings, plus a VIN decoder.
- Y Combinator Companies, Batches & Founders — the YC directory with founders and social links, filterable by batch, industry and hiring status.
- Career Site Jobs API — jobs straight from Greenhouse, Lever, Ashby, Workable and 10+ other ATS career sites.
- Workday Jobs API — every posting on any Workday career site, with facets, search, posted dates and full descriptions.
- New Job Postings Monitor — new, closed and changed postings on the career sites you watch.
- Hiring Signals API — Open Roles & Hiring Surge by Company — one row per company per run: open roles, what opened and closed, department and seniority breakdowns, and a hiring-surge flag.
- Remote Jobs API — RemoteOK, Remotive, We Work Remotely, Himalayas, Jobicy and more in one schema, deduplicated.
- Shopify Products API — any Shopify store's catalogue, variants, prices and stock signals.
- WooCommerce Products API — any WooCommerce store's catalogue, prices, variants and stock through its public Store API.
- Shopify App Store API — Shopify App Store listings by category, collection or developer: pricing plans, ratings and merchant reviews.
- Luma Events API — upcoming Luma events by city, category or calendar: dates, venue, price, capacity and organiser calendar, no host names.
- Shopify Store Monitor — price drops, sales, restocks, sell-outs and new products on any Shopify store, one row per change.
- Public Tenders API — EU TED, UK Find a Tender and Contracts Finder notices by keyword, CPV code, country, stage and deadline.
- Nonprofit & IRS 990 Lookup API — search US nonprofits and get EIN, NTEE code and multi-year Form 990 financials.
- OpenStreetMap Places API — businesses and points of interest by category and area from OpenStreetMap: name, address, coordinates, website, phone, opening hours.
Apps & games
- App Store & Google Play Reviews API — reviews from both stores with ratings, versions and developer replies.
- App Store Top Charts & App Search API — Apple top charts by country and genre, plus app search and details.
- App Store Keyword Rank Tracker — where any app ranks for any keyword on the App Store and Google Play, with rank changes and ASO suggestions.
- Steam Reviews API — Steam reviews with playtime, helpfulness and game details.
- Sports Scores & Schedules API — scores, schedules, standings, teams and headlines for the NFL, NBA, MLB, NHL, soccer and more, no key.
- App Store Monitor — App Store and Google Play listings watched between runs: new versions with release notes, price, rating and listing changes, one row per change.