vlrggapi
Important Notice
https://vlrggapi.vercel.app/is currently down because it exceeded free-tier limits. Please self-host the API for now, or wait while I look into another solution.
An Unofficial REST API for vlr.gg, a site for Valorant Esports match and news coverage.
Built by Andre Saddler
Support
If this API helps your projects, you can support ongoing maintenance and development on Ko-fi.
Quick Start
- Public base URL:
https://vlrggapi.vercel.app - Local base URL:
http://127.0.0.1:3001 - Interactive docs:
/ - Version info:
/version
curl https://vlrggapi.vercel.app/v2/news
curl "https://vlrggapi.vercel.app/v2/match?q=live_score"
curl "http://127.0.0.1:3001/v2/player?id=9×pan=all"
Highlights
- V2-first API - consistent response envelopes, validation, and per-endpoint caching
- Backwards compatibility - original unversioned endpoints are still available
- Deep match coverage - detailed match, player, team, and event match endpoints
- Operational guardrails - async HTTP, rate limiting, and bounded expensive scrapes
What's New
Match Details, Player Profiles & Team Profiles
New endpoints provide deep coverage of individual matches, players, and teams:
- Match details — per-map player stats (K/D/A, ACS, rating), round-by-round data, kill matrix, economy breakdown, head-to-head history, map veto data
- Player profiles — agent stats (17 metrics), current/past teams, event placements, total winnings, match history
- Team profiles — roster with roles/captain status, VLR rating/rank, event placements, total winnings, match history, roster transactions
- Event matches — full match list for any event with scores and VOD links
- Event detail — event info with prize pool breakdown, participating team rosters, and group/stage standings tables
- Search — cross-entity search for teams, players, and events by name or keyword
V2 API
- Standardized responses — all V2 endpoints return
{"status": "success", "data": {...}} - Input validation — invalid parameters return HTTP 400 with clear error messages
- Per-endpoint caching — in-memory TTL cache reduces load on vlr.gg
- Async HTTP — scrapers use
httpxfor non-blocking I/O
API Versions
Both the original and V2 endpoints coexist. The original endpoints (/news, /match, etc.) are preserved unchanged for backwards compatibility. V2 endpoints (/v2/news, /v2/match, etc.) are the recommended API going forward.
| Feature | Original | V2 |
|---|---|---|
| Response shape | Varies per endpoint | Consistent {"status": "success", "data": {...}} |
| Input validation | None | HTTP 400 on invalid params |
| Caching | None | Per-endpoint TTL cache |
Interactive Swagger docs are available at /.
Operational Notes
- Recommended base path - use
/v2for new integrations - Current version endpoint -
GET /versionreturns the current API version and default API - Rate limit - requests are limited to
600/minute - Error handling - V2 returns HTTP 400 for invalid input and propagates upstream failures with HTTP error codes
- Deployment targets - Vercel for the hosted API, Docker for containerized self-hosting
V2 Endpoint Overview
| Route | Query Params | Cache |
|---|---|---|
GET /v2/news |
— | 10 min |
GET /v2/match |
q (upcoming/upcoming_extended/live_score/results), num_pages, from_page, to_page, max_retries, request_delay, timeout |
30s–60s |
GET /v2/match/details |
match_id |
5 min |
GET /v2/rankings |
region |
1 hr |
GET /v2/stats |
region, timespan |
30 min |
GET /v2/events |
q (upcoming/completed/live), page |
30 min |
GET /v2/event/{id} |
event_id (path) |
30 min |
GET /v2/events/matches |
event_id |
10 min |
GET /v2/search |
q |
5 min |
GET /v2/player |
id, q (profile/matches), timespan, page |
30 min / 10 min |
GET /v2/team |
id, q (profile/matches/transactions/stats), page |
30 min / 10 min / 1 hr / 10 min |
GET /v2/health |
— | none |
See section below for full descriptions and response examples.
V2 Endpoints
All examples are collapsed — click to expand.
GET /v2/news
Params: none | Cache: 10 min
GET /v2/news
Response
{
"status": "success",
"data": {
"status": 200,
"segments": [
{
"title": "Article title",
"description": "Article summary",
"date": "April 23, 2024",
"author": "author_name",
"url_path": "https://vlr.gg/..."
}
]
}
}
GET /v2/match
Params: q (required: upcoming/upcoming_extended/live_score/results), num_pages, from_page, to_page, max_retries, request_delay, timeout
Cache: 30s (live_score), 5min (upcoming), 60s (results)
GET /v2/match?q=upcoming
Response (upcoming)
{
"status": "success",
"data": {
"status": 200,
"segments": [
{
"team1": "G2 Esports", "team2": "Leviatán",
"flag1": "flag_us", "flag2": "flag_cl",
"time_until_match": "51m from now",
"match_series": "Regular Season: Week 3",
"match_event": "Champions Tour 2024: Americas Stage 1",
"unix_timestamp": "2024-04-24 21:00:00",
"match_page": "https://www.vlr.gg/..."
}
]
}
}
GET /v2/rankings
Params: region (required — see Region Codes) | Cache: 1 hr
GET /v2/rankings?region=na
Response
{
"status": "success",
"data": {
"status": 200,
"segments": [
{
"rank": "1", "team": "Sentinels", "country": "United States",
"last_played": "22h ago", "record": "7-3", "earnings": "$295,500",
"logo": "//owcdn.net/img/..."
}
]
}
}
GET /v2/stats
Params: region (required), timespan (required: 30/60/90/all) | Cache: 30 min
GET /v2/stats?region=na×pan=30
Response
{
"status": "success",
"data": {
"status": 200,
"segments": [
{
"player": "player_name", "org": "ORG",
"rating": "1.18", "average_combat_score": "235.2",
"kill_deaths": "1.19", "kill_assists_survived_traded": "72%",
"average_damage_per_round": "158.4", "kills_per_round": "0.81",
"assists_per_round": "0.29", "first_kills_per_round": "0.19",
"first_deaths_per_round": "0.13", "headshot_percentage": "26%",
"clutch_success_percentage": "28%", "clutch_attempts": "9/57"
}
]
}
}
GET /v2/events
Browse events — use to discover event IDs for detail/matches lookups.
Params: q (optional: upcoming/completed/live), page | Cache: 30 min
GET /v2/events?q=upcoming
GET /v2/events?q=live
Response
{
"status": "success",
"data": {
"status": 200,
"segments": [
{
"title": "VCT 2025: Pacific Stage 2", "status": "ongoing",
"prize": "$250,000", "dates": "Jul 15—Aug 31", "region": "kr",
"url_path": "https://www.vlr.gg/event/..."
}
]
}
}
GET /v2/match/details
Params: match_id (required) | Cache: 5 min (30s for live)
GET /v2/match/details?match_id=595657
Response
{
"status": "success",
"data": {
"match_id": "595657",
"event": { "name": "Champions Tour 2024: Americas Stage 1", "series": "Regular Season: Week 3" },
"map_vetos": "SEN ban Breeze; C9 ban Lotus; SEN pick Ascent; C9 pick Bind; Haven remains",
"date": "April 23, 2024", "status": "completed",
"teams": [
{ "id": "2", "name": "Sentinels", "score": 2, "logo": "//owcdn.net/img/..." },
{ "id": "188", "name": "Cloud9", "score": 1, "logo": "//owcdn.net/img/..." }
],
"maps": [{
"map_name": "Ascent", "picked_by": "Sentinels", "duration": "28:41",
"score": { "team1": { "total": 13, "ct": 8, "t": 5 }, "team2": { "total": 9, "ct": 4, "t": 5 } },
"players": { "team1": [{ "name": "TenZ", "agent": "Jett", "rating": "1.32", "acs": "267", "kills": "24", "deaths": "15", "assists": "3", "kd_diff": "+9", "kast": "77%", "adr": "172.3", "hs_pct": "32%", "fk": "4", "fd": "2", "fk_diff": "+2" }], "team2": [] },
"rounds": [{ "round_num": 1, "winner": "team1", "side": "t" }]
}],
"head_to_head": [{ "event": "VCT Americas", "date": "2024/03/15", "score": "2-1", "url": "https://www.vlr.gg/..." }],
"performance": {
"kill_matrix": [{ "player": "TenZ", "kills_vs": { "opponent1": "5" } }],
"advanced_stats": [{ "player": "TenZ", "2K": "3", "3K": "1" }]
},
"economy": [{ "Team": "Sentinels", "Pistol": "50%", "Eco": "33%", "Full": "72%" }]
}
}
GET /v2/event/{event_id}
Event detail: prizes, team rosters, and standings tables.
Params: event_id (path, required — from /v2/events) | Cache: 30 min
GET /v2/event/2124
Response
{
"status": "success",
"data": {
"segments": {
"event": {
"name": "VCT 2026: Americas Stage 1", "series": "Valorant Champions Tour 2026",
"dates": "Apr 15 - May 10, 2026", "prize": "$250,000 USD",
"location": "Los Angeles, USA", "logo": "https://owcdn.net/img/..."
},
"prizes": [
{ "placement": "1st", "amount": "$100,000", "team": { "id": "120", "name": "100 Thieves", "logo": "...", "region": "United States" } },
{ "placement": "2nd", "amount": "$60,000", "team": { "id": "2355", "name": "KRÜ Esports", "logo": "...", "region": "Chile" } }
],
"teams": [{
"id": "120", "name": "100 Thieves",
"players": [{ "id": "9", "name": "Asuna", "flag": "mod-us" }],
"qualification": "NA Circuit Points"
}],
"standings": [{
"stage": "Group Stage", "columns": ["Team", "W", "L", "RD", "MRD"],
"rows": [{ "Team": "100 Thieves", "W": "4", "L": "1", "RD": "+42", "MRD": "+12" }]
}]
}
}
}
GET /v2/search
Cross-entity search for players, teams, and events.
Params: q (required) | Cache: 5 min
GET /v2/search?q=tenz
Response
{
"status": "success",
"data": {
"segments": {
"query": "tenz",
"results": {
"players": [{ "id": "9", "name": "TenZ", "img": "https://owcdn.net/img/...", "description": "", "tag": "" }],
"teams": [{ "id": "16647", "name": "TenZ and Friends", "img": "https://...", "description": "", "tag": "(inactive)" }],
"events": []
}
}
}
}
GET /v2/player
Params: id (required), q (profile/matches, default: profile), timespan (30d/60d/90d/all, default: 90d), page (1-based, default: 1) | Cache: varies
GET /v2/player?id=9&q=profile×pan=all
GET /v2/player?id=9&q=matches&page=1
Profile response
{
"status": "success",
"data": {
"info": { "name": "TenZ", "real_name": "Tyson Ngo", "avatar": "https://owcdn.net/img/...", "country": "Canada", "socials": [{ "platform": "twitter", "url": "..." }] },
"current_teams": [{ "name": "Sentinels", "tag": "SEN", "status": "Active" }],
"past_teams": [{ "name": "Cloud9", "tag": "C9", "dates": "2020–2021" }],
"agent_stats": [{ "agent": "Jett", "use_count": 150, "use_pct": "42%", "rounds": 3200, "rating": "1.15", "acs": "245.3", "kd": "1.18", "adr": "162.1", "kast": "71%", "kpr": "0.82", "apr": "0.28", "fkpr": "0.20", "fdpr": "0.14", "kills": 2624, "deaths": 2224, "assists": 896, "fk": 640, "fd": 448 }],
"event_placements": [{ "event": "Champions 2024", "placement": "1st", "prize": "$100,000", "team": "Sentinels" }],
"total_winnings": "$177,650"
}
}
Matches response
{
"status": "success",
"data": {
"matches": [{ "match_id": "595657", "event": "Champions Tour 2024: Americas Stage 1", "teams": { "team1": "Sentinels", "team2": "Cloud9" }, "score": "2-1", "date": "Apr 24, 2024" }],
"page": 1
}
}
GET /v2/team
Params: id (required), q (profile/matches/transactions/stats, default: profile), page (1-based, default: 1) | Cache: varies
GET /v2/team?id=2&q=profile
GET /v2/team?id=2&q=matches&page=1
GET /v2/team?id=2&q=transactions
GET /v2/team?id=2&q=stats
Profile response
{
"status": "success",
"data": {
"info": { "name": "Sentinels", "tag": "SEN", "logo": "https://owcdn.net/img/...", "country": "United States", "socials": [{ "platform": "twitter", "url": "..." }] },
"rating": { "vlr_rating": "1850", "rank": "1", "region": "na" },
"roster": [{ "alias": "TenZ", "real_name": "Tyson Ngo", "role": "Duelist", "is_captain": false, "avatar": "..." }],
"event_placements": [{ "event": "Champions 2024", "placement": "1st", "prize": "$100,000" }],
"total_winnings": "$1,194,000"
}
}
Matches response
{
"status": "success",
"data": {
"matches": [{ "match_id": "595657", "event": "Champions Tour 2024: Americas Stage 1", "teams": { "team1": "Sentinels", "team2": "Cloud9" }, "score": "2-1", "date": "Apr 24, 2024" }],
"page": 1
}
}
Transactions response
{
"status": "success",
"data": {
"transactions": [{ "date": "Jan 15, 2024", "action": "join", "player": "TenZ", "position": "Duelist" }]
}
}
Stats response
{
"status": "success",
"data": {
"segments": [
{
"map": "Bind",
"games": 86,
"win_pct": "71%",
"wins": 61,
"losses": 25,
"atk_first": 54,
"def_first": 32,
"atk_rwin_pct": "60%",
"atk_rw": 575,
"atk_rl": 383,
"def_rwin_pct": "53%",
"def_rw": 458,
"def_rl": 408
}
]
}
}
GET /v2/events/matches
Params: event_id (required) | Cache: 10 min
GET /v2/events/matches?event_id=2095
Response
{
"status": "success",
"data": {
"matches": [{
"match_id": "595657",
"teams": [{ "name": "Sentinels", "score": "2", "is_winner": true }, { "name": "Cloud9", "score": "1", "is_winner": false }],
"event_series": "Grand Final",
"vods": [{ "name": "VOD", "url": "https://youtube.com/..." }],
"date": "Apr 24, 2024"
}]
}
}
GET /v2/health
Params: none | Cache: none
GET /v2/health
Response
{
"status": "success",
"data": {
"https://vlrggapi.vercel.app": { "status": "Healthy", "status_code": 200 },
"https://vlr.gg": { "status": "Healthy", "status_code": 200 }
}
}
Original Endpoints
Preserved for backwards compatibility. Most return {"data": {"status": int, "segments": [...]}}. Rankings uses {"status": int, "data": [...]}. Response shapes mirror their V2 counterparts — see V2 Endpoints for examples.
| Route | Query Params |
|---|---|
GET /news |
— |
GET /match |
q (upcoming/upcoming_extended/live_score/results), pagination params |
GET /match/details |
match_id |
GET /stats |
region, timespan |
GET /rankings |
region |
GET /events |
q (upcoming/completed/live), page |
GET /event/{id} |
— (path param) |
GET /events/matches |
event_id |
GET /search |
q |
GET /player |
id, timespan |
GET /player/matches |
id, page |
GET /team |
id |
GET /team/matches |
id, page |
GET /team/transactions |
id |
GET /health |
— |
GET /match?q=upcoming — response example
{
"data": {
"status": 200,
"segments": [
{
"team1": "G2 Esports",
"team2": "Leviatán",
"flag1": "flag_us",
"flag2": "flag_cl",
"time_until_match": "51m from now",
"match_series": "Regular Season: Week 3",
"match_event": "Champions Tour 2024: Americas Stage 1",
"unix_timestamp": "2024-04-24 21:00:00",
"match_page": "https://www.vlr.gg/..."
}
]
}
}
GET /match?q=live_score — response example
{
"data": {
"status": 200,
"segments": [
{
"team1": "Team 1",
"team2": "Team 2",
"flag1": "flag_xx",
"flag2": "flag_xx",
"team1_logo": "https://...",
"team2_logo": "https://...",
"score1": "1",
"score2": "0",
"team1_round_ct": "7",
"team1_round_t": "6",
"team2_round_ct": "5",
"team2_round_t": "4",
"map_number": "1",
"current_map": "Ascent",
"time_until_match": "LIVE",
"match_event": "Event name",
"match_series": "Series name",
"unix_timestamp": "1713996000",
"match_page": "https://www.vlr.gg/..."
}
]
}
}
GET /match?q=results — response example
{
"data": {
"status": 200,
"segments": [
{
"team1": "Team Vitality",
"team2": "Gentle Mates",
"score1": "0",
"score2": "2",
"flag1": "flag_eu",
"flag2": "flag_fr",
"time_completed": "2h 44m ago",
"round_info": "Regular Season-Week 4",
"tournament_name": "Champions Tour 2024: EMEA Stage 1",
"match_page": "/318931/team-vitality-vs-gentle-mates-...",
"tournament_icon": "https://owcdn.net/img/..."
}
]
}
}
GET /stats?region=na×pan=30 — response example
{
"data": {
"status": 200,
"segments": [
{
"player": "corey",
"org": "TTR",
"rating": "1.18",
"average_combat_score": "235.2",
"kill_deaths": "1.19",
"kill_assists_survived_traded": "72%",
"average_damage_per_round": "158.4",
"kills_per_round": "0.81",
"assists_per_round": "0.29",
"first_kills_per_round": "0.19",
"first_deaths_per_round": "0.13",
"headshot_percentage": "26%",
"clutch_success_percentage": "28%",
"clutch_attempts": "9/57"
}
]
}
}
GET /rankings?region=na — response example
Note: /rankings uses a different response shape than other endpoints.
{
"status": 200,
"data": [
{
"rank": "1",
"team": "Sentinels",
"country": "United States",
"last_played": "22h ago",
"last_played_team": "vs. Evil Geniuses",
"last_played_team_logo": "//owcdn.net/img/...",
"record": "7-3",
"earnings": "$295,500",
"logo": "//owcdn.net/img/..."
}
]
}
GET /events?q=upcoming — response example
{
"data": {
"status": 200,
"segments": [
{
"title": "VCT 2025: Pacific Stage 2",
"status": "ongoing",
"prize": "$250,000",
"dates": "Jul 15—Aug 31",
"region": "kr",
"thumb": "https://owcdn.net/img/...",
"url_path": "https://www.vlr.gg/event/..."
}
]
}
}
GET /health — response example
{
"https://vlrggapi.vercel.app": {
"status": "Healthy",
"status_code": 200
},
"https://vlr.gg": {
"status": "Healthy",
"status_code": 200
}
}
Region Codes
| Code | Region |
|---|---|
na |
North America |
eu |
Europe |
ap |
Asia Pacific |
la |
Latin America |
la-s |
Latin America South |
la-n |
Latin America North |
oce |
Oceania |
kr |
Korea |
mn |
MENA |
gc |
Game Changers |
br |
Brazil |
cn |
China |
jp |
Japan |
col |
Collegiate |
Validation & Error Handling
V2 endpoints validate input and return HTTP 400 with descriptive error messages:
- Invalid region — must be one of the codes listed above
- Invalid timespan — must be
30,60,90, orall - Invalid player timespan — must be
30d,60d,90d, orall - Invalid match query — must be
upcoming,upcoming_extended,live_score, orresults - Invalid event query — must be
upcoming,completed, orlive - Invalid ID —
match_id,event_id, playerid, and teamidmust be positive integers
{
"detail": "Invalid region 'xyz'. Valid regions: ap, br, cn, col, eu, gc, jp, kr, la, la-n, la-s, mn, na, oce"
}
Original endpoints do not validate input (preserved for backwards compatibility).
Caching
V2 endpoints use an in-memory TTL cache to reduce load on vlr.gg. Cache durations per endpoint:
| Data | TTL | |---|---|---| | Live scores | 30 seconds | | Match detail (live) | 30 seconds | | Results | 60 seconds | | Upcoming matches | 5 minutes | | Match detail | 5 minutes | | Search | 5 minutes | | News | 10 minutes | | Player matches | 10 minutes | | Team matches | 10 minutes | | Event matches | 10 minutes | | Stats | 30 minutes | | Events | 30 minutes | | Event detail | 30 minutes | | Player profile | 30 minutes | | Team profile | 30 minutes | | Rankings | 1 hour | | Team transactions | 1 hour |
Original endpoints are not cached.
Installation
Requirements
- Python
3.11(matches.python-version, CI, and the Docker image) pip
git clone https://github.com/axsddlr/vlrggapi/
cd vlrggapi
python -m venv .venv
Activate the virtual environment:
# macOS / Linux
source .venv/bin/activate
# Windows PowerShell
.venv\Scripts\Activate.ps1
Install dependencies:
pip install -r requirements.txt
Run locally
python main.py
The API will be available at http://127.0.0.1:3001 and the interactive docs will be at http://127.0.0.1:3001/.
Smoke check
curl http://127.0.0.1:3001/version
curl "http://127.0.0.1:3001/v2/health"
Docker
docker compose up --build
Testing
python -m pytest tests/ -v
Built With
Contributing
Issues and pull requests are welcome.
Recommended workflow:
- Branch from
master. - Install dependencies and verify the app starts locally.
- Run
python -m pytest tests/ -v. - Open a pull request against
master.
Open a pull request or file an issue.
License
The MIT License (MIT)