Efficient Hextech Crafting Using the LoL Client API

For the last couple of years, events in League of Legends have largely revolved around passes which unlock missions. One of the main rewards come in the form of tokens which can be redeemed for content such as prestige skins, random champion shards, and more. Unfortunately the Hextech Crafting UI leaves a lot to be desired especially for bulk actions; redeeming, say, a couple thousand of tokens for random champion shards (a great way for newer players to unlock champions to play) could take upwards of half an hour of repetitive clicking. Animations make this worse by introducing a small delay for each action (although much of that can be disabled by enabling low-spec mode in the client settings).

As an example, here’s the process for redeeming a single Event Orb (~10s):

Hextech Crafting

Luckily there’s a way to make this go faster! Many developers may already be familiar with the official Riot API but it turns out the game client itself exposes a bunch of endpoints that can be queried locally (there’s a brief mention of this capability in the docs).

Connecting to the API

To get started, ensure that you’re logged into the game. You’ll then want to grab some information required to connect to the API (note: this changes after every client reset!). One method is to open the lockfile found in your LoL installation directory (e.g. D:\Riot Games\League of Legends\lockfile).

Lockfile

This is a colon-separated entry consisting of:

  1. Process name
  2. Process ID
  3. Port
  4. Password
  5. Protocol

Next, we’ll need a way to call the API. I like to use Insomnia for this but there are many other alternatives such as Postman and curl. Common parts of the API can be constructed with the above information. E.g.:

- Base URL: https://127.0.0.1:64445
- Basic Authentication:
  - Username: riot
  - Password: _svrnx0KHThyKdf6-tmlmg
API Authentication

Getting Crafty

There’s a bunch of functionality exposed by the client API but for the purposes of Hextech Crafting we’ll only be concerned with a few endpoints:

- Get a list of all items that the player owns
  - GET /lol-loot/v1/player-loot

- Get all of the craftable recipes associated to the given loot ID
  - GET /lol-loot/v1/recipes/initial-item/${lootId}

- Craft a recipe (redeem tokens, open a random champion shard, open an event orb, etc.)
  - POST /lol-loot/v1/recipes/${recipeName}/craft
    Body (JSON): [${lootId1}, ${lootId2}, ...]

Calling /lol-loot/v1/player-loot will give you a dump of all the items that you own. You can do a quick search for the item that you want to redeem. For example, Worlds 2020 tokens are represented like so:

...
{
  "asset": "",
  "count": 2156,
  "disenchantLootName": "",
  "disenchantValue": 0,
  "displayCategories": "CHEST",
  "expiryTime": -1,
  "isNew": false,
  "isRental": false,
  "itemDesc": "",
  "itemStatus": "NONE",
  "localizedDescription": "Gained from purchasing event content or completing event missions. Craft into exclusive Worlds 2020 event content. Tokens are earnable until November 9, 2020 at 11:59 p.m. PT. Tokens are purchasable until November 24, 2020 at 11:00 a.m. PT. Tokens expire November 24, 2020 at 1:00 p.m. PT.",
  "localizedName": "Worlds 2020 Token",
  "localizedRecipeSubtitle": "Forge your Worlds 2020 Tokens into exclusive event content. Tokens expire from inventory November 24, 2020 at 1:00 p.m. PT.",
  "localizedRecipeTitle": "Worlds 2020 Shop",
  "lootId": "MATERIAL_404",
  "lootName": "MATERIAL_404",
  "parentItemStatus": "NONE",
  "parentStoreItemId": -1,
  "rarity": "DEFAULT",
  "redeemableStatus": "NOT_REDEEMABLE",
  "refId": "",
  "rentalGames": 0,
  "rentalSeconds": 0,
  "shadowPath": "",
  "splashPath": "/lol-game-data/assets/ASSETS/Loot/Worlds2020_Token_490px.png",
  "storeItemId": 404,
  "tags": "",
  "tilePath": "/lol-game-data/assets/ASSETS/Loot/Worlds2020_Token_490px.png",
  "type": "MATERIAL",
  "upgradeEssenceName": "",
  "upgradeEssenceValue": 0,
  "upgradeLootName": "",
  "value": 0
},
...

The value to take note of is lootId. We can use it to query for everything that can be crafted. For example, calling /lol-loot/v1/recipes/initial-item/MATERIAL_404 results in the following truncated snippet:

...
{
  "contextMenuText": "1 Random Champion Shard",
  "crafterName": "default",
  "description": "1 Random Champion Shard",
  "displayCategories": "CHEST",
  "imagePath": "/lol-game-data/assets/ASSETS/Loot/hextech_mystery_shard_490x490.png",
  "introVideoPath": "",
  "loopVideoPath": "",
  "metadata": {
    "bonusDescriptions": [],
    "guaranteedDescriptions": [
      {
        "childLootTableNames": [],
        "childrenDescriptions": [],
        "imagePath": "",
        "localizedDescription": "",
        "localizedDescriptionLong": "",
        "lootName": "LOOTTABLE_chest_generic_2"
      }
    ],
    "tooltipsDisabled": false
  },
  "outputs": [
    {
      "lootName": "CHEST_241",
      "quantity": 1
    }
  ],
  "outroVideoPath": "",
  "recipeName": "MATERIAL_404_FORGE_22",
  "requirementText": "",
  "slots": [
    {
      "lootIds": [
        "MATERIAL_404"
      ],
      "quantity": 50,
      "slotNumber": 0,
      "tags": ""
    }
  ],
  "type": "FORGE"
},
...

Again, we’ll want to take note of a couple of fields (recipeName and lootIds). Now we can finally redeem our tokens (for random champion shards in this case) by calling /lol-loot/v1/recipes/MATERIAL_404_FORGE_22/craft, passing in lootIds as the JSON payload:

Redeem Tokens

Boom! The redeemed item should now show up in the Loot tab. This process can be repeated as many times as necessary (Insomnia has an easy way to resubmit requests at an interval by right-clicking “Send”).

Note that this is not restricted to just redeeming tokens! To save even more time we can reuse the same API endpoint to open event orbs, random champion shards, mystery emotes, and more. Simply grab the necessary information by following the steps above. I’ll open the shard that I redeemed earlier by calling /lol-loot/v1/recipes/CHEST_241_OPEN/craft with ["CHEST_241"] as the JSON payload.

Summary

The LoL game client is backed by an API that can be called directly with some ingenuity. Many popular applications such as Blitz make use of it for things like automatically changing runes in champion select. Here, we show that bulk crafting is already a possibility. It’d be great to see similar quality-of-life changes built into the client in the future.

October 25, 2020