draftify.lolDocs Open Draftify

Overlay data

If you'd rather build your own overlay than use the broadcast view, Draftify has two read-only JSON endpoints with every game's picks and bans.

The endpoints only have locked picks and bans. Selections in progress (hovers), the countdown, pauses, late requests and drafter names aren't included. If you need those, use the broadcast view, with bg=transparent to layer it over your own design. The draft room's live WebSocket connection isn't a public API and can change without notice.

The series: GET /api/series/{code}#

https://draftify.lol/api/series/k3qz9wmp4
{
  "id": "k3qz9wmp4",
  "team1Name": "Northwind",
  "team2Name": "Kestrel",
  "gameCount": 3,
  "currentGame": 2,
  "games": [
    { "number": 1, "status": "complete", "tab": "complete", "seated": [], "blueTeam": "team1" },
    { "number": 2, "status": "drafting", "tab": "current", "seated": ["blue", "red"], "blueTeam": "team2" },
    { "number": 3, "status": "lobby", "tab": "locked", "seated": [], "blueTeam": "team2" }
  ],
  "championDataPatch": "16.20.1"
}
Field Meaning
id The draft code.
team1Name, team2Name Team names. Teams aren't tied to a side; see blueTeam.
gameCount Games in the series (1–5).
currentGame The first game that isn't complete, or the last game if all are.
games[].status lobby, drafting, finalization or complete. See Game status.
games[].tab How the series tab shows: current, complete, available or locked (the game before it isn't finished).
games[].seated Sides that have a drafter in their seat.
games[].blueTeam Which team is on Blue in that game: team1 or team2.
championDataPatch The Data Dragon version the series uses for champions and art, for example 16.20.1.

An unknown or expired code returns 404 with {"error": "not_found"}.

Picks and bans: GET /api/series/{code}/results#

https://draftify.lol/api/series/k3qz9wmp4/results
{
  "id": "k3qz9wmp4",
  "createdAt": 1791400000000,
  "team1Name": "Northwind",
  "team2Name": "Kestrel",
  "gameCount": 1,
  "mode": "normal",
  "timerSeconds": 30,
  "firstSelection": false,
  "championDataPatch": "16.20.1",
  "current": 1,
  "games": [
    {
      "number": 1,
      "status": "complete",
      "version": 57,
      "blueTeam": "team1",
      "firstPick": "blue",
      "pickOrderSet": false,
      "stepIndex": null,
      "seated": [],
      "startedAt": 1791400100000,
      "completedAt": 1791400700000,
      "bans": {
        "blue": [
          { "championId": 266, "locked": true },
          { "championId": 145, "locked": true },
          { "championId": 64, "locked": true },
          { "championId": 111, "locked": true },
          { "championId": 117, "locked": true }
        ],
        "red": [
          { "championId": 897, "locked": true },
          { "championId": 222, "locked": true },
          { "championId": null, "locked": true },
          { "championId": 412, "locked": true },
          { "championId": 69, "locked": true }
        ]
      },
      "picks": {
        "blue": [
          { "championId": 498, "locked": true, "role": "bot" },
          { "championId": 497, "locked": true, "role": "support" },
          { "championId": 113, "locked": true, "role": "jungle" },
          { "championId": 61, "locked": true, "role": "mid" },
          { "championId": 58, "locked": true, "role": "top" }
        ],
        "red": [
          { "championId": 150, "locked": true, "role": "top" },
          { "championId": 234, "locked": true, "role": "jungle" },
          { "championId": 134, "locked": true, "role": "mid" },
          { "championId": 202, "locked": true, "role": "bot" },
          { "championId": 89, "locked": true, "late": true, "role": "support" }
        ]
      }
    }
  ]
}

Series fields#

Field Meaning
createdAt When the draft was created (milliseconds since 1970, UTC).
mode normal or fearless.
timerSeconds 30, 45, 60, or null when the timer is off.
firstSelection true when the series uses Separate pick order.
current The game a draft link without ?game= opens.
games Every game of the series, in order.

Game fields#

Field Meaning
number 1-based game number.
status lobby, drafting, finalization or complete.
version Goes up with every change to the game.
blueTeam team1 or team2: who is on Blue this game.
firstPick blue or red: the side that picks first. Always blue unless the series uses Separate pick order.
pickOrderSet With Separate pick order, whether this game's pick order has been chosen.
stepIndex While drafting: the current step, 0 to 19 (see Step order). Otherwise null.
seated Sides with a drafter in their seat.
startedAt, completedAt When the draft started and finished (milliseconds), or null.
bans, picks Five slots per side: bans.blue[0] is Blue ban 1, picks.red[4] is Red pick 5.

Slots#

Field Meaning
championId Riot's numeric champion id (the key in Data Dragon), or null.
locked false: the draft hasn't reached this slot yet. true with a championId: that champion was locked in. true with null: the slot was left empty, because the drafter locked None or the timer ran out.
late true when the slot was filled with Late Selection. Absent otherwise.
role Picks only: top, jungle, mid, bot or support. Present only once the game is complete, and only for picks the drafter gave a role (Role confirmation). Roles are hidden until then.

Game status#

Status Meaning
lobby Waiting for drafters to take their seats and ready up.
drafting Picks and bans in progress. stepIndex says whose turn it is.
finalization All 20 steps are done. Drafters can still undo, set roles or fill late slots for a short time. Picks can still change.
complete Final. Roles are revealed.

An approved undo can take a game from finalization back to drafting, and clear slots that were locked. Don't treat a locked slot as final until the game is complete.

Step order#

The 20 steps follow the standard tournament order. F is the side in firstPick and S is the other side:

Steps (stepIndex) Order
0–5 Bans: F S F S F S
6–11 Picks: F S S F F S
12–15 Bans: S F S F
16–19 Picks: S F F S

Each side fills its own slots 1 to 5 in order. The full table with Blue first is on the Drafting page.

Champion names and images#

championId is Riot's numeric champion key. To get names and image file names, load Data Dragon's champion list for the series' patch:

https://ddragon.leagueoflegends.com/cdn/{championDataPatch}/data/en_US/champion.json

Each entry has key (the numeric id as a string), id (the name used in image URLs, for example MonkeyKing for Wukong) and name (the display name). The latest version is the first entry of https://ddragon.leagueoflegends.com/api/versions.json.

These are the image URLs Draftify itself uses. {id} is the Data Dragon id, and {skin} is a skin number (0 is the base skin):

Image URL
Square icon https://ddragon.leagueoflegends.com/cdn/{patch}/img/champion/{id}.png
Loading-screen portrait (308×560) https://ddragon.leagueoflegends.com/cdn/img/champion/loading/{id}_{skin}.jpg
Centred splash https://ddragon.leagueoflegends.com/cdn/img/champion/centered/{id}_{skin}.jpg
Full splash https://ddragon.leagueoflegends.com/cdn/img/champion/splash/{id}_{skin}.jpg
Icon fallback (CommunityDragon) https://raw.communitydragon.org/latest/plugins/rcp-be-lol-game-data/global/default/v1/champion-icons/{championId}.png

One quirk: Fiddlesticks' loading-screen and centred-splash files are named FiddleSticks, not Fiddlesticks. Skin numbers and names are in https://ddragon.leagueoflegends.com/cdn/{patch}/data/en_US/champion/{id}.json (entries with a parentSkin are chromas).

Example#

A minimal browser script that prints the current game's picks:

const code = "k3qz9wmp4";

const draft = await (await fetch(`https://draftify.lol/api/series/${code}/results`)).json();
const dd = await (
  await fetch(`https://ddragon.leagueoflegends.com/cdn/${draft.championDataPatch}/data/en_US/champion.json`)
).json();
const byKey = new Map(Object.values(dd.data).map((c) => [Number(c.key), c]));

const game = draft.games[draft.current - 1];
const teamOn = (side) =>
  (side === "blue") === (game.blueTeam === "team1") ? draft.team1Name : draft.team2Name;

for (const side of ["blue", "red"]) {
  console.log(`${teamOn(side)} (${side})`);
  for (const slot of game.picks[side]) {
    const champ = byKey.get(slot.championId);
    const label = champ ? champ.name : slot.locked ? "No pick" : "…";
    const art = champ && `https://ddragon.leagueoflegends.com/cdn/img/champion/loading/${champ.id}_0.jpg`;
    console.log(" ", label, slot.role ?? "", art ?? "");
  }
}

To keep it live, fetch again every second or two, and redraw only when the game's version changes.

Result images#

Draftify also renders each draft as an image, the same one link previews show:

https://draftify.lol/api/series/{code}/card.png?game=2

It's a PNG, 1200 pixels wide. Without ?game=, a multi-game series with a finished game gets the whole-series card, and otherwise the current game's. Images of finished games are cached for a day, and live ones for 30 seconds.