An Unofficial REST API for vlr.gg, a site for Valorant Esports match and news coverage.
Built by Andre Saddler
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
- 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
- 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
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 /.
Fetches the latest Valorant esports news.
- Params: none
- Cache: 10 minutes
GET /v2/news
{
"status": "success",
"data": {
"status": 200,
"segments": [
{
"title": "Article title",
"description": "Article summary",
"date": "April 23, 2024",
"author": "author_name",
"url_path": "https://vlr.gg/..."
}
]
}
}Fetches match data by type.
- Params:
q(required) —upcoming,upcoming_extended,live_score, orresultsnum_pages— pages to scrape (default: 1)from_page/to_page— page range (overridesnum_pages)max_retries— retry attempts per page (default: 3)request_delay— delay between requests in seconds (default: 1.0)timeout— request timeout in seconds (default: 30)
- Cache: 30s (live_score), 5min (upcoming), 1hr (results)
GET /v2/match?q=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/..."
}
]
}
}Fetches team rankings for a region.
- Params:
region(required) — see Region Codes
- Cache: 1 hour
GET /v2/rankings?region=na
{
"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/..."
}
]
}
}Fetches player statistics for a region and timespan.
- Params:
region(required) — see Region Codestimespan(required) —30,60,90, orall
- Cache: 30 minutes
GET /v2/stats?region=na×pan=30
{
"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%"
}
]
}
}Fetches Valorant events.
- Params:
q(optional) —upcomingorcompleted(omit for both)page(optional) — page number for completed events (default: 1)
- Cache: 30 minutes
GET /v2/events?q=upcoming
{
"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/..."
}
]
}
}Fetches detailed data for a specific match.
- Params:
match_id(required) — VLR.GG match ID
- Cache: 5 minutes (30s for live matches)
GET /v2/match/details?match_id=595657
{
"status": "success",
"data": {
"event": { "name": "Champions Tour 2024: Americas Stage 1", "series": "Regular Season: Week 3" },
"teams": [
{ "name": "Sentinels", "score": 2, "logo": "//owcdn.net/img/..." },
{ "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": [
{
"team": "Sentinels",
"player": "TenZ",
"agent": "Jett",
"rating": "1.32",
"acs": "267",
"kills": "24",
"deaths": "15",
"assists": "3",
"kast": "77%",
"adr": "172.3",
"hs_pct": "32%",
"fk": "4",
"fd": "2"
}
]
}
],
"rounds": [
{ "round_number": 1, "team1_win": true, "team2_win": false, "team1_side": "ct", "team2_side": "t" }
],
"head_to_head": [
{ "event": "VCT Americas", "match": "Sentinels vs Cloud9", "score": "2-1" }
],
"streams": [{ "name": "English", "link": "https://twitch.tv/..." }],
"performance": {
"kill_matrix": [{ "player": "TenZ", "kills_against": { "opponent1": 5 } }],
"advanced_stats": [{ "player": "TenZ", "2k": 3, "3k": 1, "4k": 0, "5k": 0, "clutch_1v1": 1 }]
},
"economy": [
{ "team": "Sentinels", "pistol": "50%", "eco": "33%", "semi_buy": "60%", "full_buy": "72%" }
]
}
}Fetches a player profile.
- Params:
id(required) — VLR.GG player IDtimespan—30d,60d,90d, orall(default:90d)
- Cache: 30 minutes
GET /v2/player?id=9×pan=all
{
"status": "success",
"data": {
"info": {
"name": "TenZ",
"real_name": "Tyson Ngo",
"avatar": "https://owcdn.net/img/...",
"country": "Canada",
"socials": [{ "platform": "twitter", "url": "https://twitter.com/TenZOfficial" }]
},
"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"
}
}Fetches paginated match history for a player.
- Params:
id(required) — VLR.GG player IDpage— page number (default: 1)
- Cache: 10 minutes
GET /v2/player/matches?id=9&page=1
{
"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
}
}Fetches a team profile.
- Params:
id(required) — VLR.GG team ID
- Cache: 30 minutes
GET /v2/team?id=2
{
"status": "success",
"data": {
"info": {
"name": "Sentinels",
"tag": "SEN",
"logo": "https://owcdn.net/img/...",
"country": "United States",
"socials": [{ "platform": "twitter", "url": "https://twitter.com/Sentinels" }]
},
"rating": { "vlr_rating": "1850", "rank": "1", "region": "na" },
"roster": [
{
"alias": "TenZ",
"real_name": "Tyson Ngo",
"role": "Duelist",
"is_captain": false,
"avatar": "https://owcdn.net/img/..."
}
],
"event_placements": [
{ "event": "Champions 2024", "placement": "1st", "prize": "$100,000" }
],
"total_winnings": "$1,194,000"
}
}Fetches paginated match history for a team.
- Params:
id(required) — VLR.GG team IDpage— page number (default: 1)
- Cache: 10 minutes
GET /v2/team/matches?id=2&page=1
{
"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
}
}Fetches roster transaction history for a team.
- Params:
id(required) — VLR.GG team ID
- Cache: 1 hour
GET /v2/team/transactions?id=2
{
"status": "success",
"data": {
"transactions": [
{
"date": "Jan 15, 2024",
"action": "join",
"player": "TenZ",
"position": "Duelist"
}
]
}
}Fetches the match list for a specific event.
- Params:
event_id(required) — VLR.GG event ID
- Cache: 10 minutes
GET /v2/events/matches?event_id=2095
{
"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"
}
]
}
}Returns health status of the API and vlr.gg.
- Params: none
- Cache: none
GET /v2/health
{
"status": "success",
"data": {
"https://vlrggapi.vercel.app": {
"status": "Healthy",
"status_code": 200
},
"https://vlr.gg": {
"status": "Healthy",
"status_code": 200
}
}
}These endpoints are preserved for backwards compatibility. Most return {"data": {"status": int, "segments": [...]}}. The /rankings endpoint returns {"status": int, "data": [...]} instead.
| 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), page |
GET /events/matches |
event_id |
GET /player |
id, timespan |
GET /player/matches |
id, page |
GET /team |
id |
GET /team/matches |
id, page |
GET /team/transactions |
id |
GET /health |
— |
GET /news — response example
{
"data": {
"status": 200,
"segments": [
{
"title": "Riot introduces changes to Premier, adds new Invite Division",
"description": "Riot looks to streamline Premier promotions and Challengers qualification with upcoming changes.",
"date": "April 23, 2024",
"author": "thothgow",
"url_path": "https://vlr.gg/336099/riot-introduces-changes-to-premier-adds-new-invite-division"
}
]
}
}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%"
}
]
}
}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
}
}| 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 |
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
upcomingorcompleted - 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).
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 |
| Upcoming matches | 5 minutes |
| Match detail | 5 minutes |
| News | 10 minutes |
| Player matches | 10 minutes |
| Team matches | 10 minutes |
| Event matches | 10 minutes |
| Stats | 30 minutes |
| Events | 30 minutes |
| Player profile | 30 minutes |
| Team profile | 30 minutes |
| Rankings | 1 hour |
| Results | 1 hour |
| Team transactions | 1 hour |
Original endpoints are not cached.
git clone https://github.com/axsddlr/vlrggapi/
cd vlrggapi
pip install -r requirements.txtpython main.pyServes on http://0.0.0.0:3001.
docker-compose up --buildpython -m pytest tests/ -vFeel free to submit a pull request or an issue!
The MIT License (MIT)