Player match stats
The per-player stat line — which fields are always present, which are nullable, and the map_number trap.
GET /v1/{game}/matches/{id}/stats returns one row per player per map, plus a whole-match aggregate
row per player.
The map_number trap
map_number is null on the whole-match aggregate row. Every player therefore appears
maps + 1 times: once per map, once in total.
rows = get(f"/v1/cs2/matches/{match_id}/stats")["data"]
per_map = [r for r in rows if r["map_number"] is not None]
aggregate = [r for r in rows if r["map_number"] is None]Summing all rows double-counts every player. This is the single most common mistake against this endpoint.
Always present
kills, assists, deaths, adr and rating are on every row. rating is our own computed
rating, not a third party's — don't compare it numerically against a rating from elsewhere.
Nullable
The richer detail comes from a source that doesn't cover every match, so these are null rather
than 0 where unavailable — an honest absence, not a claim that nothing happened:
kast, headshots, first_kills, first_deaths, trade_kills, trade_deaths, clutches,
multikills_2k/3k/4k/5k, damage, utility_value.
KAST units differ by endpoint
kast here is a fraction between 0 and 1 — multiply by 100 for the percentage usually shown.
On a round row it is a count of 0–5 players, and on a team profile the *_pct fields are
already 0–100. Three different units for related ideas; check which endpoint you're reading.
team_id
team_id is the team the player played for in this match, which is not always their current
team — rosters change, and stand-ins happen. It is nullable where attribution couldn't be resolved.
Use it rather than the player's own team_id when attributing historical performance.
Field reference
Prop
Type
For what ADR, KAST and rating mean as concepts, the marketing site has explainers at /learn/cs2-adr and /learn/cs2-kast. This page documents the fields as served.