Steam libraries and hours
Steam games API: owned games and playtime
List the games Steam exposes for an account, sorted by lifetime playtime, with Steam's minute values and decimal hours, and optional playtime over the last two weeks.
Updated
curl --fail-with-body \
-H "Authorization: Bearer $WOK_API_KEY" \
"https://woksteamapi.com/v1/games?steam_id=76561198000000001&include_recent=1"Endpoints
A WOK key with all-purpose or Players access. Free Developer keeps its own quota, day and minute limits and the WOK Discord membership rule. Each single read uses one quota unit.
GET /v1/games | Visible Steam games and playtime |
|---|---|
GET /v1/games/recent | Steam playtime over the last two weeks |
POST /v1/games/batch | Visible Steam game hours for up to 20 accounts |
POST /v1/games/recent/batch | Recent Steam game hours for up to 20 accounts |
Request
Parameters of GET /v1/games, as published in the OpenAPI description.
| Parameter | Required | Accepted values | Notes |
|---|---|---|---|
steam_id | Required | string | A 17-digit SteamID64. Profile URLs and vanity names are not accepted here. |
include_recent | Optional | integer (default 0) | Set to 1 to add recent_playtime from GetRecentlyPlayedGames and fill known two-week minutes for matching games. Default 0 keeps the owned-games-only path. |
achievement_appid | Optional | integer | Adds achievement progress for this one visible game. |
Response fields
Fields of a 200 response. A type that includes null means Steam may not publish that value.
| Field | Type | Meaning |
|---|---|---|
steam_id | string | The SteamID64 the response describes. |
game_count | integer or null | Number of games Steam reports for the account; null when unknown. |
games | array of object | Games Steam exposes for the account, sorted by lifetime playtime. |
games.appid | integer | Steam AppID. |
games.name | string | Game name. |
games.playtime_forever | integer or null | Lifetime playtime in minutes, as Steam reports it. |
games.playtime_2weeks | integer or null | Playtime over the last two weeks in minutes; null when unknown. |
games.playtime_hours | number or null | Lifetime playtime in decimal hours. |
games.playtime_2weeks_hours | number or null | Two-week playtime in decimal hours. |
games.achievement_progress | object | Progress for the game named by achievement_appid. |
total_playtime_minutes | integer or null | Sum over visible games only. |
total_playtime_hours | number or null | The same total in decimal hours. |
visibility | string: visible, unknown | unknown when the games array is empty: a private library and an empty library cannot be told apart. |
achievement_appid | integer | The AppID you asked achievement progress for. |
achievement_status | string | Present with achievement_appid: whether progress for that one game was available. |
recent_playtime | object | Present with include_recent=1: the result of Steam's recently played list. |
complete | boolean | True only for a nonempty unique valid-AppID list with all lifetime minutes and a matching source game_count; empty, hidden or incomplete data retains null totals. |
What your code should handle
The cases that most often turn into wrong numbers in a product.
Empty does not mean private. An empty games array comes with visibility=unknown. Steam gives no way to tell a private library from an empty one.
Totals cover visible games. total_playtime_minutes and total_playtime_hours are summed over the games Steam exposes, not over everything the account owns.
Recent hours are optional. include_recent=1 adds two-week minutes for matching games. Missing recent data stays unknown; it is not zero.
Status codes
Errors carry a typed code and, where it applies, Retry-After. Respect it on 429 and 503.
| Status | Meaning |
|---|---|
200 | OK |
400 | Invalid request |
401 | Missing or invalid API key |
402 | Quota exhausted or required add-on is not active |
403 | Resource is private or restricted; discord_required means free access requires current WOK Discord membership |
422 | Query or JSON body validation failed |
429 | Rate limit exceeded |
502 | Upstream service failed |
503 | Required upstream capability is unavailable; discord_unavailable means free membership verification should be retried |
Related requests
The same key reads these. Batches use one quota unit per unique account or pair, including cached results.
GET /v1/games/recent
Steam playtime over the last two weeks.
| Field | Required | Accepted values | Notes |
|---|---|---|---|
steam_id | Required | string | A 17-digit SteamID64. Profile URLs and vanity names are not accepted here. |
POST /v1/games/batch
Visible Steam game hours for up to 20 accounts.
| Field | Required | Accepted values | Notes |
|---|---|---|---|
steamids | Required | array of string (1 to 20 entries) | User SteamID64 strings, deduplicated in first occurrence order. |
appids | Optional | array of integer (1 to 50 entries) | Optional local filter for returned games, applied after the shared owned-games cache read. Omit to return every exposed game. |
include_recent | Optional | boolean (default False) | Add recent_playtime from GetRecentlyPlayedGames and fill known per-game recent minutes for matching AppIDs; up to two cold Steam lookups per account, with unchanged quota. |
POST /v1/games/recent/batch
Recent Steam game hours for up to 20 accounts.
| Field | Required | Accepted values | Notes |
|---|---|---|---|
steamids | Required | array of string (1 to 20 entries) | SteamID64 strings. Duplicates are removed before quota is counted. |
appids | Optional | array of integer (1 to 50 entries) | Optional local recent-list filter; source game_count and recent totals remain unfiltered. |
Questions
Do I need a Valve Steam Web API key?
No. WOK holds the Steam Web API key on its servers and makes the Steam call for you. Your server sends a WOK key in the Authorization header.
Can I tell a private library from an account with no games?
No. Both return an empty games array, so WOK reports visibility=unknown instead of guessing.
How do I read hours for many players?
POST /v1/games/batch accepts 1 to 20 SteamID64 strings and uses one quota unit per unique ID. An optional list of up to 50 AppIDs filters the result without another Steam request.
Where does two-week playtime come from?
From Steam's recently played list. Use GET /v1/games/recent on its own, or include_recent=1 on GET /v1/games to fill it in for matching games.
Steam account bansSteam friend listsSteam achievementsSteam level and badges