What's in the data
An honest inventory of what exists, what's thin, and what isn't there at all.
Before you design around this API, here's what it actually contains.
Ask the API itself
/v1/{game}/coverage is the authoritative answer, and it's deliberately unflattering:
curl -H "Authorization: Bearer $ESPORTSODDS_API_KEY" \
"https://api.esportsodds.gg/v1/cs2/coverage"Each row carries a status:
| Status | Meaning |
|---|---|
live | Available now |
pending_validation | Built, held back until it clears an accuracy bar |
schema_ready | The shape exists but isn't populated |
planned | Intended, not built |
licence_required | Blocked on rights, not engineering |
Read it before you build, not after.
The layers
Fixtures and results — teams, tournaments, schedule, format, scores, winners. The broadest and deepest layer.
Map results — per-map scores with half-by-half splits, and overtime where it happened.
Player stats — kills/assists/deaths, ADR and our own rating on every row; KAST, opening duels, trades, clutches, multi-kills and utility where the source carried them. On top of the rows, the player endpoints serve last-12-month figures with percentiles, per-map figures, recent matches, team history and a weapon profile.
Round stats — two rows per round, one per team: economy, opening duels, trades, clutches, bomb events, utility. This is where genuine tactical analysis lives.
Player depth — weapons, grenades, hitgroups, killer/victim duels and flash pairs. The newest and least universal layer.
Lineups and rosters — two different things. A match's lineup is the roster snapshot we took before it
started (include=lineups, ?has=lineups); capture began on 9 July 2026, so an older match has none. The five
a team actually fielded are known afterwards: the whole-match stat rows (map_number null) carry a team_id,
and GET /v1/cs2/teams/{id}/roster-history serves a team's recent fielded fives (up to 100 per call), with a
continuity field that tells a roster change from a rename.
Odds — one de-vigged market line per outcome, as a time series, with movement fields and closing flags. It starts in July 2026 and not every match has one: see Coverage by year.
Derived — Glicko-2 ratings, leaderboards, team form, head-to-head, per-map records, playstyle profiles, roster history.
To see these layers on one real match, exactly as the API returned them, read CS2 match data in JSON.
Coverage by tier
Depth falls away with tournament tier. Share of completed matches with each layer, last 90 days, measured on 2026-10-11:
| Tier | Matches | Map scores | Player stats | Round stats | Player depth | Vetoes (since 26 Sep) |
|---|---|---|---|---|---|---|
| S | 159 | 100% | 99% | 99% | 99% | 100% |
| A | 123 | 100% | 98% | 98% | 98% | 100% |
| B | 1,532 | 93% | 80% | 79% | 80% | 45% |
| C | 2,092 | 83% | 59% | 59% | 59% | 7% |
Most of the gap is matches whose demos were never parsed anywhere we can use, or that were never played (forfeits). Vetoes for B and C matches have been patchy since 26 September, when our usual feed stopped carrying them; we fill what we can from a second source. The counts in Checking depth for yourself are always current.
Events with no tier hold fixtures and results first. In the 90 days to 17 October 2026, 205 completed matches sat at untiered events: 107 of them (52%) had a played map, and none had player or round stats.
How far back. S and A tier events go back to late 2020, and B tier to May 2021. C tier and unranked events start in June 2026: from then on we hold their fixtures, results and whatever depth exists, but nothing earlier.
Which small events. Not every small event reaches us. Checked against a public list of C tier events for the six weeks to 12 October 2026, we held 59 of 102. Most of the ones we missed were small LANs, regional amateur leagues and online cups.
Coverage by year
If you are pulling the archive, this is what each year holds. Share of completed matches with each layer, all tiers together, measured on 2026-10-13 and rounded down:
| Year | Matches | Map scores | Player stats | Round stats | Vetoes | Market line |
|---|---|---|---|---|---|---|
| 2020 (from 14 Nov) | 126 | 100% | 100% | 100% | 100% | none |
| 2021 | 1,047 | 99% | 99% | 99% | 98% | none |
| 2022 | 1,581 | 97% | 97% | 96% | 92% | none |
| 2023 | 4,925 | 92% | 89% | 89% | 83% | none |
| 2024 | 5,341 | 94% | 93% | 93% | 75% | none |
| 2025 | 5,503 | 93% | 89% | 89% | 91% | none |
| 2026 (to 13 Oct) | 8,386 | 89% | 74% | 73% | 68% | 2,630 matches |
2026 is lower because it is the first year with C tier and unranked events, which carry the least depth (see the table above). S and A tier matches are at 95% or more for map scores, player stats and round stats in every year.
Odds history starts on 2 July 2026. No match before that date has a market line. Since then, 2,630 of 4,531 completed matches carry one (58%). If your work needs prices for older matches, this API does not have them.
What's thin
Worth knowing before you filter on it:
roleon players: about 14% populated. Filtering by role excludes everyone whose role is unknown, which is most.seedon tournament participants: alwaysnull— no upstream we ingest publishes seeding.- Depth: check
data_available.depth; it's absent on plenty of matches. - Lineups: since capture began on 9 July 2026, 67% of completed matches have a snapshot (S 98%, A 84%,
B 80%, C 62%, none at events with no tier; 4,674 matches, measured 17 October 2026). Check
data_available.lineupsper match. Where there is none, the whole-match stat rows say who played. tieron tournaments: ~96% populated,SthroughC.
What isn't there
- Per-book odds. One aggregate line, never individual bookmaker prices or names.
- The model line. Empty until it clears its gate — check
/v1/cs2/model/metrics. - Team logos.
logo_urlis always empty; no redistribution rights. - Sub-second live ticks. The WebSocket pushes at ingestion cadence.
Known limitations has the full list.
Checking depth for yourself
Rather than trusting a figure in a doc that could go stale, count:
# How many completed matches have round-level data?
curl -H "Authorization: Bearer $ESPORTSODDS_API_KEY" \
"https://api.esportsodds.gg/v1/cs2/matches?status=completed&has=rounds&limit=1"?has= accepts any subset of maps,stats,map_stats,vetoes,rounds,depth,lineups,odds, so you can
size the population that actually supports your analysis before committing to it.
To see what one fully covered match looks like, every layer from the match row down to single rounds, read sample responses.
AI assistants (MCP)
Ask Claude, Cursor or any MCP client about CS2 matches, teams and players, answered from the esportsodds.gg API through the official MCP server.
Sample responses
Real responses from one completed match, from the match row down to single rounds, so you can see the data before you sign up.