KO.LOL League of Legends Stats ko.lol Download

API docs lite

Derived aggregates only, one explicit patch per call, everything carries its games

The ko.lol API serves the desktop app and this site's build, and its aggregate routes are open to read. This page is the whole public contract: the routes, their parameters, the patch rule that trips everyone once, the cache windows, and how to cite what you fetch. The base URL is https://api.ko.lol.

The contract in numbers

Each figure here is restated in full in its section below.

Public routes
13
Store games
108,616 recorded ranked games
Rate limit
600 requests per minute on /v1/web/
Cache
60 s live query routes
Patch
16.14

What every response carries

The store behind every route holds 108,616 recorded ranked games right now, and every response stamps generatedAt and its game counts, so staleness and thinness are visible in the document itself.

ko.lol publishes worked out aggregates only, never raw Riot match data. Estimates in these responses arrive with a 95% range, a games count and a provenance word, and cells under their floor arrive as null with the count so far. Quote the number with its games or you are quoting a different claim than the one we made.

The public GET routes 13 routes

Parameters mirror the fetchers this site itself is built with. Anything not listed here is not public.

The public GET routes of https://api.ko.lol Route catalog as of the build date; the footer of this page carries the store stamp
route what it answers parameters patch
GET /v1/status Store counts, the list of patches with recorded games, and crawler state per region none no patch. This is where the patch list comes from
GET /v1/tierlist Champion and role rows: score, tier, win impact with range, games, pick rate, and the formula block with every constant patch required; role optional (top, jungle, mid, bot, support; omit for all); queue optional (420 ranked solo default, 450 ARAM) ?patch= required
GET /v1/runes/{champion}/{role} Whole recorded rune pages with games and wins, single-slot counts, and damage-type splits champion key and role in the path ?patch= required
GET /v1/skills/order Per-level skill shares, the modal max order, and the first-max comparison with its verdict championKey, role, patch ?patch= required
GET /v1/jungle/path Recorded jungle routes with camp times and a win delta per route championKey no patch. The route aggregates the whole store, and the response says so
GET /v1/rdd Patch-boundary item reports: effect in wins per 100 games, range, and games on each side patch ?patch= required
GET /v1/bundle Champions, items, item names and recorded builds for one patch. About 6.4 MB patch ?patch= required
GET /v1/web/matchups/{champion} Opponent rows with counts, shrunk estimates and verdicts. Sorted best matchup first, so the counters are the tail of the list champion key in the path; patch required; role optional (omit for the most played role) ?patch= required
GET /v1/web/synergies/{champion} Teammate rows ranked by the win rate delta against the champion's own average, with the same floors and formula block champion key in the path; patch required; role optional ?patch= required
GET /v1/web/matchup/{a}/{b} One exact pair, both sides: estimates, the head-to-head record, and the lane at minute 15 where measured both champion keys in the path; patch required; role optional ?patch= required
GET /v1/web/data The catalog of data explorer metrics that exist, the metrics that are not measured yet with the reason, and the pool disclosure patch ?patch= required
GET /v1/web/data/{metric} One explorer's rows with estimates, floors, coverage and caveats metric id in the path (listed by /v1/web/data); patch required; role and champion optional where the catalog says they apply ?patch= required
GET /v1/web/profile/{platform}/{slug} A built player profile, or one of five honest non-ready answers: pending, moved, not found, ambiguous, unavailable. The non-200 statuses carry a real JSON body platform and slug in the path; the slug is the Riot ID in lowercase with # replaced by a hyphen no patch. A profile is the player's recorded window, not one patch's cell
Path parameters are shown in braces. Champion keys are Data Dragon keys (Ahri, MonkeyKing), roles are top, jungle, mid, bot and support, and the patch value must come from /v1/status. Requests need no header and no key on any route listed here.

The patch rule

The one mistake everybody makes once, written down so you make it zero times.

  1. Every route marked "?patch= required" answers HTTP 404 without it. There is no server side default on purpose: a default would quietly serve numbers from a patch nobody is playing.
  2. Get the patch list from https://api.ko.lol/v1/status, in the clickhouse patches array, each entry with its recorded games.
  3. Sort patch numbers as numbers, never as text. As text, "16.9" sorts above "16.14" and you build on the wrong patch. Split on the dot and compare the parts as integers. Do not use the latestPatch field in the status response for this: it is sorted as text and can point at an old patch.
  4. Worked examples for the current patch: https://api.ko.lol/v1/tierlist?patch=16.14 and https://api.ko.lol/v1/runes/Ahri/mid?patch=16.14.

Cache windows and pacing

What freshness to expect, and how to be a polite caller.

  • /v1/status, /v1/tierlist, /v1/runes and /v1/rdd answer from live queries behind a cache of about 60 seconds.
  • /v1/bundle is rebuilt about every 5 minutes and is the heaviest document here, about 6.4 MB for a patch.
  • /v1/jungle/path and /v1/skills/order read tables refilled by batch jobs, so their freshness is the generatedAt stamp in the response, not the clock.
  • The /v1/web/ routes are rate limited at 600 requests per minute. Past the limit you get 429, and a busy query engine can answer 503; both carry a Retry-After header. Sleep exactly what it says and retry. Our own build does the same and never needs more.
  • Cache on your side by URL: the same URL with the same patch answers the same document until the store moves, and every response says when it was generated.

How to cite a number

The format that keeps the claim attached to its evidence.

  • Cite as: ko.lol, patch 16.14, n games, page URL.
  • Always carry the patch and the sample size with the number.
  • Cells reading "not enough games yet", and null estimates with their counts, are not results. Do not quote them as results.
  • Verdicts come in three words and there is no fourth: beats, too close, not enough games. A tie is an answer.
  • Say whose games these are: recorded ranked games found by following Diamond players and the people they play with, on the regions the status route lists. It is not every rank and it is not every region.

The machine-readable version of this page, with the page family index for the website, is at /llms.txt.

What is not public

The line, drawn once.

Everything not in the table above needs a signed request. That class covers player profiles' compute, per-match analysis, recommendations and scouting: the key ships only inside the desktop app, no key is issued to third parties, and those routes are deliberately not documented here. Raw Riot match JSON is never served on any route, signed or not.

The numbers behind the signed class are published as HTML on this site, each page with its ranges, counts and structured data, so nothing readable is locked behind the signature. If a route here changes shape, the change lands on the changelog.