Skip to content

An Unofficial REST API for vlr.gg, a site for Valorant Pro Esports match results and news.

License

Notifications You must be signed in to change notification settings

axsddlr/vlrggapi

Repository files navigation

vlrggapi

An Unofficial REST API for vlr.gg, a site for Valorant Esports match and news coverage.

Built by Andre Saddler

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
  • 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

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 httpx for 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 /.

V2 Endpoints

GET /v2/news

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/..."
      }
    ]
  }
}

GET /v2/match

Fetches match data by type.

  • Params:
    • q (required) — upcoming, upcoming_extended, live_score, or results
    • num_pages — pages to scrape (default: 1)
    • from_page / to_page — page range (overrides num_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/..."
      }
    ]
  }
}

GET /v2/rankings

Fetches team rankings for a region.

  • Params:
  • 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/..."
      }
    ]
  }
}

GET /v2/stats

Fetches player statistics for a region and timespan.

  • Params:
    • region (required) — see Region Codes
    • timespan (required) — 30, 60, 90, or all
  • Cache: 30 minutes
GET /v2/stats?region=na&timespan=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%"
      }
    ]
  }
}

GET /v2/events

Fetches Valorant events.

  • Params:
    • q (optional) — upcoming or completed (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/..."
      }
    ]
  }
}

GET /v2/match/details

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%" }
    ]
  }
}

GET /v2/player

Fetches a player profile.

  • Params:
    • id (required) — VLR.GG player ID
    • timespan30d, 60d, 90d, or all (default: 90d)
  • Cache: 30 minutes
GET /v2/player?id=9&timespan=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"
  }
}

GET /v2/player/matches

Fetches paginated match history for a player.

  • Params:
    • id (required) — VLR.GG player ID
    • page — 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
  }
}

GET /v2/team

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"
  }
}

GET /v2/team/matches

Fetches paginated match history for a team.

  • Params:
    • id (required) — VLR.GG team ID
    • page — 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
  }
}

GET /v2/team/transactions

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"
      }
    ]
  }
}

GET /v2/events/matches

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"
      }
    ]
  }
}

GET /v2/health

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
    }
  }
}

Original Endpoints

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
  }
}

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, or all
  • Invalid player timespan — must be 30d, 60d, 90d, or all
  • Invalid match query — must be upcoming, upcoming_extended, live_score, or results
  • Invalid event query — must be upcoming or completed
  • Invalid IDmatch_id, event_id, player id, and team id must 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
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.

Installation

git clone https://github.com/axsddlr/vlrggapi/
cd vlrggapi
pip install -r requirements.txt

Run locally

python main.py

Serves on http://0.0.0.0:3001.

Docker

docker-compose up --build

Testing

python -m pytest tests/ -v

Built With

Contributing

Feel free to submit a pull request or an issue!

License

The MIT License (MIT)

About

An Unofficial REST API for vlr.gg, a site for Valorant Pro Esports match results and news.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors 11