A player's weapon and hit-group profile
The player's weapon and hit-group totals over their matches in the last 12 months. Weapon data is recorded per match, never per map. The eight weapons with the most kills are listed and the rest are folded into one `other` row. `matches` is how many matches carry weapon data, and `window.through` is the date of the newest of them. A player with none returns empty lists. Enveloped `{"data": PlayerWeapons}`.
The player's weapon and hit-group totals over their matches in the last 12 months. Weapon data is recorded per match, never per map. The eight weapons with the most kills are listed and the rest are folded into one other row. matches is how many matches carry weapon data, and window.through is the date of the newest of them. A player with none returns empty lists. Enveloped {"data": PlayerWeapons}.
Primary auth (live). Authorization: Bearer <api-key> — the header takes precedence over the query fallback. The raw key is hashed (SHA-256, hex) and looked up in api.keys.key_hash; the raw value is never stored.
In: header
Path Parameters
Game slug. cs2 is the only populated title today; an un-onboarded game 404s cleanly.
Resource identifier — either a UUID or the resource's human-readable slug, scoped to {game}. /v1/cs2/teams/natus-vincere and /v1/cs2/teams/019f23d1-fb5c-7987-b522-47c3a5e72111 address the same row, so you can go straight from a slug you already have without first looking up its id.
Slugs work on teams, players and tournaments. Matches have no slug, so a match id must be a UUID. Either way, an identifier that resolves to nothing returns 404 not_found.
A team or a player also answers to a slug it was renamed away from, as long as no current team or player holds that slug — so a link made before a rename keeps working. The row returned carries its current slug.
Response Body
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/cs2/players/019f2858-e253-7f3d-bdff-bc7738bd1036/weapons"{ "data": { "window": { "months": 12, "through": "2026-10-10T13:45:00Z" }, "matches": 82, "weapons": [ { "slug": "awp", "name": "AWP", "class": "Rifle", "kills": 1401, "headshots": 154, "hits": 1585, "shots": 3443, "damage": 130239 }, { "slug": "ak-47", "name": "AK-47", "class": "Rifle", "kills": 888, "headshots": 523, "hits": 2508, "shots": 16469, "damage": 88409 }, { "slug": "m4a4", "name": "M4A4", "class": "Rifle", "kills": 209, "headshots": 90, "hits": 721, "shots": 4378, "damage": 20821 }, { "slug": "m4a1", "name": "M4A1", "class": "Rifle", "kills": 183, "headshots": 80, "hits": 576, "shots": 3099, "damage": 18630 }, { "slug": "glock-18", "name": "Glock-18", "class": "Pistols", "kills": 153, "headshots": 118, "hits": 448, "shots": 1920, "damage": 16612 }, { "slug": "usp-s", "name": "USP-S", "class": "Pistols", "kills": 136, "headshots": 125, "hits": 332, "shots": 1312, "damage": 13668 }, { "slug": "desert-eagle", "name": "Desert Eagle", "class": "Pistols", "kills": 114, "headshots": 92, "hits": 220, "shots": 825, "damage": 12513 }, { "slug": "dual-berettas", "name": "Dual Berettas", "class": "Pistols", "kills": 93, "headshots": 71, "hits": 245, "shots": 994, "damage": 9204 }, { "slug": "other", "name": "Other", "class": "Other", "kills": 368, "headshots": 202, "hits": 3074, "shots": 18489, "damage": 59008 } ], "hit_groups": [ { "hit_group": "Chest", "hits": 3759, "damage": 135899, "kills": 1223 }, { "hit_group": "Generic", "hits": 2172, "damage": 22135, "kills": 69 }, { "hit_group": "Head", "hits": 1808, "damage": 129598, "kills": 1502 }, { "hit_group": "Stomach", "hits": 1124, "damage": 43871, "kills": 463 }, { "hit_group": "RightArm", "hits": 619, "damage": 23417, "kills": 213 }, { "hit_group": "LeftArm", "hits": 206, "damage": 8712, "kills": 85 }, { "hit_group": "RightLeg", "hits": 170, "damage": 4803, "kills": 36 }, { "hit_group": "LeftLeg", "hits": 146, "damage": 4271, "kills": 23 } ] }}{ "error": { "code": "not_found", "message": "not found", "request_id": "019f3d18-c15f-7319-81a7-343e8a80a578" }}{ "error": { "code": "not_found", "message": "not found", "request_id": "019f3d18-c15f-7319-81a7-343e8a80a578" }}{ "error": { "code": "rate_limited", "message": "rate limit exceeded", "request_id": "019f3d18-c15f-7319-81a7-343e8a80a578" }}A player's last-12-month figures with percentiles GET
One player's figures over their recorded maps in the last 12 months, each with its percentile among every player who has a player page. A recorded map is one played to a result on a competitive map, in a completed Counter-Strike 2 match that was not a walkover, where the player's line is complete and attributed to one of the two teams that played. Every rate is a ratio of sums over the maps that carry its inputs (ADR and KAST weighted by rounds), never an average of per-map figures; `n` is how many maps a figure uses. A figure from fewer than 10 maps is `null`, and so is its percentile. A percentile is the share of the population with a strictly lower value, floored to one decimal place, so it is never 100; `population.n` is the population's size. `level` is `established`, `listed` or `none`, by the rule in `population.level_definition`. `definition` carries the exact wording of every rule, so you can quote it rather than restate it. `nationality` and `role` are `null` when unknown; the response never carries a real name. Enveloped `{"data": PlayerPerformance}`.
A single player GET
One player by id. Adds `own_rank` — the player's position on our own leaderboard — but only when you ask for it with `?rank=1` or `?include=rank`. Players carry no `external_rank`.