LoL live match stats

New feature on Riot’s pro game broadcast site: a live stats board. It updates once a second in your browser showing you game stats. Also features for Twitter messages, game stream info, etc. It’s the stats I’m interested in.

Stats scoreboard

Here’s the data on display:

  • Match type. Game #. Games won / lost by each team. Team and player names.
  • Kills in current game. Also objectives: inhibs, barons, dragons, towers.
  • Total team gold.
  • For each player: kills/death/assists, CS, and gold.

Data contents

The game stats are implemented with a web socket. (There’s also some JSONP being polled for other features; the stats are a web socket.) I wrote a Python program to record the data. They generally send one message a second, about 500 bytes, updates to things like player gold, kills, etc. It’s a pretty efficient implementation.

The data on the web socket is mostly what you’d expect to implement that display. Messages usually contain updates on player stats: total gold, current gold, experience points, and player position. Variables are only in the JSON blob if their value has changed. A bunch of oddball updates sometimes come through for things like CS, player kills, etc. And then teamStats updates for tower kills, etc. They’re also tracking player double kills, triple kills, etc. Nothing in the stream about item purchases that I’ve seen.

There’s also some special messages. The first message on the socket is about 14k and contains all the data that ordinary isn’t changing, stuff like player name. When a new game starts the info about what champions are in the game is sent along. When a game ends there’s a gameComplete message. That kind of thing.

The most interesting thing I’ve found in the data stream is player position. It’s currently not being used by Riot’s web client. Should be possible to use that to animate a version of the game. riftwalk.gg had something like that based on replays before it got shut off, would be nice to feed this stream to that visualization code.

Technical details

My Python client is having the socket closed on it every 90 seconds. I just re-open it for now, seems to work. The web client in Chrome doesn’t seem to be doing that. Wireshark tells me that there’s a ping/pong Chrome is exchanging every 45 seconds. I’m guessing the Python client isn’t responding to pong and after two failed pings the connection closes. A bit confused why the pong doesn’t come through, the Python library looks like it just handles that for me.

Update: I looked in Wireshark and found the Python client is sending pong responses, but they’re getting TCP fragmented into two packets maybe because of the way the async writing code works. I’ve opened an issue on GitHub seeing if my analysis is correct and whether it’s something that could change. Update 2: I guessed right! The author changed the code to not fragment the packet and now I can stay connected. Yay!

The web socket hosted at ws://livestats.proxy.lolesports.com/stats. The socket requires a JSON web token to connect, which is some signed blob, although it’s not tied to any personal secret like a password login. I pulled one out of my browser and decoded it via jwt.io, it contains a bunch of IDs. Also has what looks like an expiration date, token is good for a week. I just pulled the token out of my browser and reused it in the Python code.