Published 26 June 2026 pythondata-analysisgaming

Scouting Korean solo queue for off-meta Lulu builds

Using the Riot Games API to analyse a high-elo KR Lulu one-trick's match history and surface build adaptations that haven't reached mainstream guides yet.

Korean solo queue is where the meta gets discovered. New builds, rune pages, and lane assignments surface on KR weeks before they appear on guide sites or in competitive play. If you want to know what’s coming, you watch KR.

I built a small Python pipeline that pulls a player’s ranked match history from the Riot Games API, filters to a specific champion, and breaks down exactly what they build and run against each lane opponent. The goal: find adaptations that aren’t in any guide yet.

The test subject is a high-elo KR Lulu one-trick. Lulu top is already an unconventional pick — but the builds this player runs are even more unusual.

The pipeline

We pull 250 ranked solo-queue games from a high-elo KR Lulu one-trick via the Riot Match-V5 API. Each match is cached locally as JSON. From the match details and timeline events we extract: the lane opponent, whether the game was won, the rune page, starting items (first 60s of timeline events), and end-of-game core items.

Show code
In [1]:
from api import RiotAPIClient
from transform import build_dataframes
from report import aggregate_data

client = RiotAPIClient(api_key)
puuid = client.get_puuid(game_name, tag_line)
match_ids = client.get_match_ids(puuid, count=250, queue=420)

matches = {mid: client.get_match(mid) for mid in match_ids}
timelines = {mid: client.get_timeline(mid) for mid in match_ids}

matches_df, items_df, runes_df = build_dataframes(
    matches, timelines, puuid, champion_name="Lulu"
)
agg = aggregate_data(matches_df, items_df, runes_df)

qualifying = {k: v for k, v in agg.items() if v['total'] >= 3}
print(f"{len(match_ids)} ranked matches fetched (patches 15.24 \u2013 16.3)")
print(f"{len(matches_df)} Lulu games with a recognised lane opponent")
print(f"{len(qualifying)} distinct matchups (3+ games each)")
250 ranked matches fetched (patches 15.24 – 16.3)
164 Lulu games with a recognised lane opponent
26 distinct matchups (3+ games each)

The pipeline normalises everything into three DataFrames — one row per match, one per item event, one per rune selection — then aggregates per lane opponent.

Show code
In [2]:
summary.head(12)
GamesWin RateTop KeystoneBoots
Fiora5100%ElectrocuteSwiftness
Dr. Mundo4100%ElectrocuteSwiftness
Darius3100%Phase RushSwiftness
Anivia3100%Electrocute
Vladimir683%ElectrocuteSwiftness
Jax1080%ElectrocuteSteelcaps
Nautilus475%Summon AeryLucidity
Aurora1173%ElectrocuteMerc Treads
Renekton1070%ElectrocuteSteelcaps
Rumble1369%ElectrocuteSwiftness / Merc
Zaahen1369%ElectrocuteSwiftness
Sion1765%ElectrocuteSwiftness

The interesting pattern: this player runs Phase Rush *only* into Darius — a matchup where most players take Electrocute or Aery. Against Nautilus (likely a support-turned-top queue game) they switch to Summon Aery entirely, paired with support items like Dream Maker and Shurelya's. That's not a build you'd find on any guide site.

Win rate by matchup

The first thing to look at: which matchups does this player actually win?

Win rate by lane opponent (3+ games)

Lulu top destroys immobile melee: Fiora (100% over 5 games), Dr. Mundo (100%), Jax (80% over 10 games). The worst matchups are champions with sustained all-in that Lulu can’t peel — K’Sante (29%), Yasuo (25%), Irelia (43%).

Keystone adaptation

Electrocute is the default — but not the only option. The interesting part is when this player deviates.

Keystone usage across all 164 Lulu games

Boot choice by matchup type

The boot pick is the clearest signal of how this player reads the lane opponent.

Boot choice by opponent category

Boots of Swiftness into tanks has the highest win rate — these are the matchups Lulu controls. Steelcaps into AD is defensive; the win rate drops because these are the harder matchups. The boot choice doesn’t cause the win rate — it reflects the difficulty.

The interesting finds

The raw numbers are useful but not surprising. The builds are where it gets interesting.

Phase Rush into Darius. Every guide says Electrocute on Lulu top. This player runs Phase Rush exclusively into Darius — 100% of 3 games, 100% win rate. The logic: Darius wants to stack his passive in extended trades. Phase Rush lets Lulu proc it with one combo and disengage before the bleed stacks. It’s a matchup-specific adaptation you won’t find on any stats site because the sample sizes are too small to surface.

Support Lulu into Nautilus. When matched against Nautilus top (likely a support player autofilled), this player switches to an entirely different build: Summon Aery keystone, Dream Maker, Shurelya’s Battlesong, Ionian Boots. They read the game state — if the opponent is playing a support champion, the game is going to be decided by teamfights, not lane. So they build to enable their team instead of trying to carry the lane.

Boot choice as a matchup read. The boot choice maps cleanly to opponent type:

  • Plated Steelcaps into AD all-in (Irelia, Jax, Renekton, Ambessa, Riven)
  • Mercury’s Treads into AP threats (Aurora, Ryze, Rumble, Ornn)
  • Boots of Swiftness into tanks and low-threat lanes (Sion, Zaahen, Vladimir, Dr. Mundo, Fiora)

The Swiftness choice into Fiora is the non-obvious one — most players would go Steelcaps into a Fiora. But at this level, the Fiora matchup is about kiting and spacing, not tanking auto-attacks. Swiftness helps more.

Takeaway

The value of scouting KR isn’t copying builds. It’s seeing how the best players adapt. The default Lulu top build (Electrocute, Doran’s Ring, Luden’s) works into most matchups. But a player at this level has 3–4 variations they deploy based on what they’re facing. That level of matchup-specific adaptation is what separates a one-trick from someone who just plays the champion.

Source code: league-analysis on GitHub.