TutorialCS2 API tutorials

An HLTV API alternative, in four swaps.

HLTV publishes no official API, so most HLTV-style code fetches web pages and breaks when they change. Almost all of it does four jobs: recent results, a player's ratings, the team ranking and live scores. Each has one documented CS2 API endpoint; this guide swaps them one at a time.

  • 4 endpoint swaps
  • Python and Node.js
  • Not affiliated with HLTV
GET /cs2/teams/rankings?limit=3200 OK
$ curl "https://api.citoapi.com/api/v1/cs2/teams/rankings?limit=3" \ -H "x-api-key: $CITO_API_KEY"
{  "success": true,  "meta": {    "ranking": "world",    "rankingDate": "2026-10-03"  },  "data": [    {      "rank": 1,      "teamName": "Spirit",      "points": 1000    },    {      "rank": 2,      "teamName": "Vitality",      "points": 676    },    {      "rank": 3,      "teamName": "FURIA",      "points": 524    }    ...  ]}

Which endpoint replaces each job?

Results, player stats, the ranking and live scores each map to a single endpoint, and the IDs are stable, so you can store them. Teams and players also take a readable slug, which spares you a lookup step.

JobCS2 API endpointNotes
Recent resultsGET /cs2/matches/resultsSeries score, event, format, maps; page with page and limit.
A player's ratingsGET /cs2/players/{slug}/matchesOne row per map: kills, deaths, ADR, KAST, rating.
Team rankingGET /cs2/teams/rankings or /cs2/rankings/vrsWorld ranking or Valve Regional Standings, with change.
Live scoresGET /cs2/matches/liveSeries score, map in play, map score, round.

Swap 1: How do I get recent results?

One call returns finished matches newest first with the final series score. Filter by team with /cs2/teams/{slug}/results instead of walking a results page.

Python
import os, requests

API = "https://api.citoapi.com/api/v1/cs2"
H = {"x-api-key": os.environ["CITO_API_KEY"]}

for m in requests.get(f"{API}/matches/results", headers=H, params={"limit": 10}).json()["data"]:
    print(m["eventName"], "|", m["team1Name"], m["team1Score"], "-", m["team2Score"], m["team2Name"])

Swap 2: How do I get a player's rating and ADR?

GET /cs2/players/{slug}/matches returns one line per map with rating, ADR and KAST, so recent form is an average over the rows you choose. Career numbers are on /cs2/players/{slug}/career.

Python: rating and ADR over the last 20 maps
rows = requests.get(f"{API}/players/zywoo/matches", headers=H, params={"limit": 20}).json()["data"]
rated = [r for r in rows if r["rating"] is not None]
print("maps:", len(rated))
print("rating:", round(sum(r["rating"] for r in rated) / len(rated), 2))
print("ADR:", round(sum(r["adr"] for r in rated if r["adr"] is not None) / len(rated), 1))

Swap 3: How do I get the team ranking?

GET /cs2/teams/rankings returns the world ranking with points and change since the previous table; GET /cs2/rankings/vrs returns the Valve Regional Standings. meta.rankingDate says which week you have.

Node.js 18+
const res = await fetch("https://api.citoapi.com/api/v1/cs2/rankings/vrs?limit=10", {
  headers: { "x-api-key": process.env.CITO_API_KEY },
})
const { data, meta } = await res.json()
console.log("VRS", meta.rankingDate)
for (const t of data) console.log(t.rank, t.teamName, t.points, t.change)
Top 10 of the Valve Regional Standings (352 teams) from GET /cs2/rankings/vrs, ranking date 2026-10-03. Fetched from the production CS2 API on 3 Oct 2026, 19:54 UTC.
RankTeamPointsChangeRegion
1Spirit2,048–Europe
2Vitality1,925▲1Europe
3Legacy1,894▼1South America
4MOUZ1,874–Europe
5Falcons1,863–Europe
6FURIA1,834▲1South America
7G21,811▼1Europe
8FUT1,796–Europe
9Aurora1,742–Europe
10Astralis1,619▲5Europe

Swap 4: How do I get live scores?

Poll GET /cs2/matches/live, or keep the SSE stream at /cs2/live/stream open and have updates pushed. Each match carries the series score, the map in play, its score and the current round.

Node.js 18+
const res = await fetch("https://api.citoapi.com/api/v1/cs2/matches/live", { headers: { "x-api-key": process.env.CITO_API_KEY } })
for (const m of (await res.json()).data) {
  console.log(`${m.team1Name} ${m.team1Score}-${m.team2Score} ${m.team2Name} | ${m.currentMap} ${m.currentMapScore?.team1}-${m.currentMapScore?.team2} R${m.currentRound}`)
}

What changes for my code after the swap?

Requests return JSON in one documented shape instead of HTML you parse, so a website redesign no longer breaks your app. Rate limits are published per plan, and a 429 says exactly how long to wait in Retry-After instead of an IP block.

Frequently asked questions

Something missing? Email support@citoapi.com.

Does HLTV have an official API?

No. HLTV does not publish an official public API, so libraries that call themselves an HLTV API read its web pages.

What is the best HLTV API alternative for Python?

A documented CS2 API called with requests. The CS2 API covers results, per-map player ratings, the world ranking and VRS, and live scores, with a free key.

Can I get HLTV-style player ratings from an API?

Yes. GET /cs2/players/{slug}/matches returns rating, ADR and KAST for each map, and /career has the career totals.

Is the CS2 API affiliated with HLTV?

No. CS2 API is operated by Cito API and is not affiliated with HLTV.

See pricing

Build CS2 live score apps

Free is for building and testing. Paid plans add commercial use, real-time live data and the full archive.