Home
Softono

Vlrggapi

Open source MIT Python
209
Stars
70
Forks
2
Issues
4
Watchers
3 months
Last Commit

 About Vlrggapi

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

Platforms

Web Self-hosted

Languages

Python

Need Help Installing Vlrggapi?

We provide expert installation service for this software. Our team will install, configure, and secure Vlrggapi on your server. plans start at just $30.

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.

Buy Me a Coffee at ko-fi.com

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&timespan=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 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 /.

Operational Notes

  • Recommended base path - use /v2 for new integrations
  • Current version endpoint - GET /version returns 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&timespan=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&timespan=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, 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, completed, or live
  • 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
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:

  1. Branch from master.
  2. Install dependencies and verify the app starts locally.
  3. Run python -m pytest tests/ -v.
  4. Open a pull request against master.

Open a pull request or file an issue.

License

The MIT License (MIT)