Counter-Strike 2 API
BetaLive matches down to the round, results with every map score, per-map player stats, teams, players, events, and the world and VRS rankings. This is the endpoint reference; the CS2 API overview covers plans, coverage and skin prices.
CS2 is in beta. The data is live and checked continuously, but if something looks wrong (a score, a stat line, a roster, a missing match), email support@citoapi.com with the endpoint you called and the match, team or player id. Reports go straight to the people fixing it.
https://api.citoapi.com/api/v1Webhooks: a signed POST when a match starts, a round ends, a bomb is planted or a result is final. CS2 webhooks
Quick start
curl "https://api.citoapi.com/api/v1/cs2/matches/recent?limit=5" \
-H "x-api-key: YOUR_API_KEY"Every response is { success, data, meta }. Ids look like cs2-match-2398421, cs2-team-9565 and cs2-player-11893; teams and players also accept their slug (vitality, zywoo). Times are ISO 8601 in UTC.
Full endpoint reference
Every CS2 endpoint, with parameters, a curl example and a real response, grouped by area.
Endpoints
GET/api/v1/cs2/liveLive MatchesMatches in progress: series score, map in play, map score and round.
/api/v1/cs2/livecurl "https://api.citoapi.com/api/v1/cs2/live" \
-H "x-api-key: YOUR_API_KEY"GET/api/v1/cs2/live/{matchId}/stateStateOne live match: round, round score, sides, players, bomb.
/api/v1/cs2/live/{matchId}/statecurl "https://api.citoapi.com/api/v1/cs2/live/{matchId}/state" \
-H "x-api-key: YOUR_API_KEY"GET/api/v1/cs2/live/streamStreamServer-Sent Events push of live updates. Every plan; billed like polling (see below).
/api/v1/cs2/live/streamcurl "https://api.citoapi.com/api/v1/cs2/live/stream" \
-H "x-api-key: YOUR_API_KEY"WS/api/v1/cs2/live/wsWsWebSocket with a room per match: snapshot on subscribe, then every score, round, map and bomb change. Live WebSockets plans.
/api/v1/cs2/live/wscurl "https://api.citoapi.com/api/v1/cs2/live/ws" \
-H "x-api-key: YOUR_API_KEY"GET/api/v1/cs2/matches/upcomingUpcoming ScheduleThe schedule, soonest first. Add ?include=odds for each match's bookmaker odds in the same call, ?bestOf=3 for BO3s only.
/api/v1/cs2/matches/upcomingcurl "https://api.citoapi.com/api/v1/cs2/matches/upcoming" \
-H "x-api-key: YOUR_API_KEY"GET/api/v1/cs2/matches/past?bestOf=3PastFinished matches, newest first: last 7 days by default, ?days= up to 90 or ?from=/?to=. bestOf=1, 3 or 5 keeps one series length.
/api/v1/cs2/matches/past?bestOf=3curl "https://api.citoapi.com/api/v1/cs2/matches/past?bestOf=3" \
-H "x-api-key: YOUR_API_KEY"GET/api/v1/cs2/matches/recentRecent MatchesLatest results with every map and its score.
/api/v1/cs2/matches/recentcurl "https://api.citoapi.com/api/v1/cs2/matches/recent" \
-H "x-api-key: YOUR_API_KEY"GET/api/v1/cs2/matches/{matchId}MatchIdOne match: maps, veto, event, streams.
/api/v1/cs2/matches/{matchId}curl "https://api.citoapi.com/api/v1/cs2/matches/{matchId}" \
-H "x-api-key: YOUR_API_KEY"GET/api/v1/cs2/matches/{matchId}/player-statsPlayer StatsPer-map player lines: kills, deaths, assists, ADR, KAST, rating.
/api/v1/cs2/matches/{matchId}/player-statscurl "https://api.citoapi.com/api/v1/cs2/matches/{matchId}/player-stats" \
-H "x-api-key: YOUR_API_KEY"GET/api/v1/cs2/maps/{mapId}/economyEconomyRound-by-round economy per player: start money, spend, equipment value, buy type, purchases.
/api/v1/cs2/maps/{mapId}/economycurl "https://api.citoapi.com/api/v1/cs2/maps/{mapId}/economy" \
-H "x-api-key: YOUR_API_KEY"GET/api/v1/cs2/props?market=kills_maps_1_2PropsPick'em player props (Underdog, Sleeper): kills and headshots on maps 1-2, graded L5/L10. Pro and above.
/api/v1/cs2/props?market=kills_maps_1_2curl "https://api.citoapi.com/api/v1/cs2/props?market=kills_maps_1_2" \
-H "x-api-key: YOUR_API_KEY"GET/api/v1/cs2/matches/{matchId}/propsPropsOne match's prop lines, every app side by side with the spread between them.
/api/v1/cs2/matches/{matchId}/propscurl "https://api.citoapi.com/api/v1/cs2/matches/{matchId}/props" \
-H "x-api-key: YOUR_API_KEY"GET/api/v1/cs2/teams/{teamIdOrSlug}TeamIdOrSlugTeam profile, current roster (players and coach) and recent results.
/api/v1/cs2/teams/{teamIdOrSlug}curl "https://api.citoapi.com/api/v1/cs2/teams/{teamIdOrSlug}" \
-H "x-api-key: YOUR_API_KEY"GET/api/v1/cs2/teams?ids=vitality,mouz,spiritList TeamsUp to 50 teams in one call (also /players and /matches); one request per 10 ids.
/api/v1/cs2/teams?ids=vitality,mouz,spiritcurl "https://api.citoapi.com/api/v1/cs2/teams?ids=vitality,mouz,spirit" \
-H "x-api-key: YOUR_API_KEY"GET/api/v1/cs2/teams/{teamIdOrSlug}/map-pool/vs/{opponentIdOrSlug}OpponentIdOrSlugTwo teams map by map: win rates, pick/ban rates, head-to-head maps and the edge.
/api/v1/cs2/teams/{teamIdOrSlug}/map-pool/vs/{opponentIdOrSlug}curl "https://api.citoapi.com/api/v1/cs2/teams/{teamIdOrSlug}/map-pool/vs/{opponentIdOrSlug}" \
-H "x-api-key: YOUR_API_KEY"GET/api/v1/cs2/players/{playerIdOrSlug}PlayerIdOrSlugPlayer profile and current team.
/api/v1/cs2/players/{playerIdOrSlug}curl "https://api.citoapi.com/api/v1/cs2/players/{playerIdOrSlug}" \
-H "x-api-key: YOUR_API_KEY"GET/api/v1/cs2/players/{playerIdOrSlug}/statsPlayerIdOrSlug StatsCareer totals and per-map stat lines.
/api/v1/cs2/players/{playerIdOrSlug}/statscurl "https://api.citoapi.com/api/v1/cs2/players/{playerIdOrSlug}/stats" \
-H "x-api-key: YOUR_API_KEY"GET/api/v1/cs2/rankingsRankingsWorld ranking. Add ?source=vrs for Valve's VRS ranking.
/api/v1/cs2/rankingscurl "https://api.citoapi.com/api/v1/cs2/rankings" \
-H "x-api-key: YOUR_API_KEY"GET/api/v1/cs2/rankings/vrs?before=2025-06-02VrsVRS as it stood before a date, back to August 2024 (pre-match rankings for models).
/api/v1/cs2/rankings/vrs?before=2025-06-02curl "https://api.citoapi.com/api/v1/cs2/rankings/vrs?before=2025-06-02" \
-H "x-api-key: YOUR_API_KEY"GET/api/v1/cs2/events/upcomingUpcoming ScheduleTournaments starting soon. Also /events/live and /events/recent.
/api/v1/cs2/events/upcomingcurl "https://api.citoapi.com/api/v1/cs2/events/upcoming" \
-H "x-api-key: YOUR_API_KEY"GET/api/v1/cs2/search?q=vitalitySearchTeams, players, events and matches by name.
/api/v1/cs2/search?q=vitalitycurl "https://api.citoapi.com/api/v1/cs2/search?q=vitality" \
-H "x-api-key: YOUR_API_KEY"GET/api/v1/cs2/autocomplete?q=vitAutocompleteTypeahead: up to 10 best matches in a few KB. ?expand=full for the full search shape.
/api/v1/cs2/autocomplete?q=vitcurl "https://api.citoapi.com/api/v1/cs2/autocomplete?q=vit" \
-H "x-api-key: YOUR_API_KEY"These are the main ones. Every CS2 route, with its parameters and a real example response, is in the OpenAPI document (tag CS2).
Filter by series length (BO1, BO3, BO5)
Add bestOf to any CS2 match list to keep one series length: 1, 3, 5, or a comma list such as 3,5. The filter runs before paging, so limit, page and meta.total count only matching matches. Any other value returns 400 INVALID_BEST_OF.
# Upcoming BO3 matches
curl "https://api.citoapi.com/api/v1/cs2/matches/upcoming?bestOf=3" \
-H "x-api-key: YOUR_API_KEY"
# Finished BO3 matches from the last 30 days
curl "https://api.citoapi.com/api/v1/cs2/matches/past?bestOf=3&days=30" \
-H "x-api-key: YOUR_API_KEY"
# The last BO3 between two teams
curl "https://api.citoapi.com/api/v1/cs2/teams/vitality/matches?opponent=mouz&type=completed&bestOf=3&limit=1" \
-H "x-api-key: YOUR_API_KEY"bestOf works on /cs2/matches, /matches/upcoming, /matches/past, /matches/results, /matches/today, /cs2/live, team match lists (/teams/{team}/matches, /upcoming, /results), head-to-head (/h2h/{team}/{opponent}), event match lists and /players/{player}/matches. Your plan's history window still applies to past matches.
Live data
Poll GET /cs2/live for everything in progress, then GET /cs2/live/{matchId}/state for one match. In the live list, score is the series (maps won) and currentMapScore is the map being played.
Push instead of polling. GET /cs2/live/stream sends every update as it happens (Server-Sent Events, add ?matchId= to follow one match). An open stream counts toward your monthly quota like polling: one request when it connects, then one for every 15 seconds it stays open. When the quota runs out it sends an error event and closes.
curl -N "https://api.citoapi.com/api/v1/cs2/live/stream" \
-H "x-api-key: YOUR_API_KEY" \
-H "Accept: text/event-stream"If full live tracking goes quiet for a match, a backup takes over within about a minute. The state then carries the series score and the map in play, without rounds or players, until full tracking returns.
Live WebSocket
wss://api.citoapi.com/api/v1/cs2/live/ws pushes the same events as the SSE stream (score, round, map and bomb changes) to one socket, with a room per match. Frames don't count toward your monthly requests. Included on Scale and Enterprise; on Pro with the Live WebSockets add-on (+$15/mo). Turn it on and test it from Dashboard → WebSockets.
- Auth: your API key in the
x-api-keyheader,Authorization: Bearer YOUR_API_KEY, or?apiKey=(browsers can't set headers on a WebSocket; proxy through your server so the key stays private). - Subscribe:
{"action":"subscribe","rooms":["match:cs2-match-2400024"]}, or"rooms":["all"]for every live match. Up to 32 rooms per connection.unsubscribetakes the same shape;{"action":"ping"}answers withpong. - Shortcut:
?matchId=cs2-match-2400024or?rooms=match:cs2-match-2400024,allon the URL subscribes at connect.
import WebSocket from "ws";
const ws = new WebSocket("wss://api.citoapi.com/api/v1/cs2/live/ws", {
headers: { "x-api-key": process.env.CITO_API_KEY },
});
ws.on("message", (raw) => {
const msg = JSON.parse(String(raw));
if (msg.type === "ready") {
ws.send(JSON.stringify({ action: "subscribe", rooms: ["match:cs2-match-2400024"] }));
}
// subscribed | cs2.live.snapshot | cs2.live.update | ping | pong | error
console.log(msg.type, msg);
});Messages from the server:
ready: sent first, withstream: "cs2.live", the rooms you hold and the message formats.subscribed/unsubscribed: the rooms you now hold.cs2.live.snapshot: once per match room when you subscribe.team1,team2,seriesScore,currentMap,currentRound,roundScore,roundTimeSeconds,bombPlantedandplayers.cs2.live.update: every change.matchId,status,team1Score/team2Score(rounds on the current map),currentMap,currentRound,roundTimeSeconds,bombPlanted,playerStatsChangedandcapturedAt. WhenplayerStatsChangedis true, fetchGET /cs2/live/{matchId}/statefor the new player lines.pingevery 15 seconds, anderrorwith acode(BAD_ROOMS,INVALID_JSON,UNKNOWN_ACTION) for a message it can't use.
A refused connection gets an HTTP error instead of the upgrade: 401 MISSING_API_KEY or 401 INVALID_API_KEY, and 403 WEBSOCKETS_REQUIRED when your plan doesn't include Live WebSockets. The SSE stream above works on every plan.
Plans
Choose a plan or read rate limits and pricing.