Help:Leaguepedia API

From Leaguepedia | League of Legends Esports Wiki
Jump to: navigation, search

This page documents Leaguepedia's API, which can be used for querying League of Legends esports schedules, statistics, players, rosters, roster changes, articles, interviews, tournament results, and nearly any other piece of data available on the wiki.

This page is intended to be used by developers who want to query our data. It is not a tutorial for people without previous development experience. This is not an official Riot resource. We are a third-party site. There may be errors or omissions in our data, and the API is made available without guarantee of stability or accuracy.

Our API is made available as a courtesy. As such, beyond this documentation you're on your own for figuring things out. We have a Discord Support Server if you need help, but in-depth help is not guaranteed.

Row IDs should NOT be used as permanent primary keys in your data. They change every time the Cargo data is recreated. In general, you shouldn't rely on any field we have as a permanent primary key, as the wiki's content always will come first for development concerns.

Please join the Discord Support Server to receive important updates.

An unofficial wrapper for this API is available here. Ping Tolki in the Discord server linked above for support.

Commonly-addressed issues:

  • The API works by you making SQL queries to our database, it's not what you might expect when you first hear "API for getting data." Even if you want 1 piece of information, you make a query that will return that one data point.
  • Please do not ever use _pageName as a condition or a value, this field is automatically populated in tables but will almost never be what you actually want. See Don't use _pageName for more information (this is a very indepth, technical, not very relevant article, only read if you are extremely curious). Generally OverviewPage is populated in a table for use instead of _pageName, sometimes there's another intended key. Ask in the support server if you need help.

Projects Using the API[edit]

Below is a list of projects that use the API. Feel free to add any other examples for reference.

  • League of Elo: Elo-based team strength model. All data is acquired through the API.
  • LoL player stats: View LoL player stats. All data is acquired through the API.
  • LoL team stats: View LoL team stats. All data is acquired through the API.
  • Lol Worlds Predictions: Regional and Temporal Elo-based team strength model trained with a Genetic Algorithm for the maximization of the Worlds Pick'Em score. All data is acquired through the API.

MediaWiki API[edit]

The MediaWiki action API is a web service that allows access to some wiki functions like page operations, search and user authentication so that you may be able to edit or query the wiki using a bot or program.

Resources[edit]

Python Packages[edit]

The documentation provides code examples using the following python packages:

Example code to log into the wiki using mwclient:

import mwclient
site = mwclient.Site('lol.fandom.com', path='/')

#Logging in is required if you are editing the wiki, otherwise it is optional
site.login('RheingoldRiver@Python', BOT_PASSWORD)

Cargo[edit]

Full list of tables at Special:CargoTables

Cargo is an SQL wrapper that we use for all of our databases. You may access information in the database in a few ways:

  1. Use Special:ViewData on a web browser
  2. Run the forms located at Category:Query_Forms on a web browser (eg. Special:RunQuery/MatchHistoryGame)
  3. Use the API through the MediaWiki API using action=cargoquery in the MediaWiki API (via mwclient)

Note that the Forms in 2 are actually just custom queries running on top of 1. You can see how these queries are made by looking at the settings of the modules (eg. Module:MatchHistoryGame/Settings)

You can see generic Cargo API documentation here.

Limits[edit]

  • 5,000 results per query if you are an admin
  • 500 result per query otherwise

Please add a small delay between queries (1-2 seconds). If the server gets stressed as a result of a huge number of queries, you may be rate-limited for some time.

Fields[edit]

See also: Special:ViewData (must be logged in)

To run a Cargo query, you will need to specify:

Field Required Description
tables Yes One or more table names (Special:CargoTables, more information below)
fields Yes Columns to return. Full list of fields in Category:Cargo Declaration Modules. (Cargo does not support * or wildcards)
limit No Maximum number of results to return. Can be 'max' or integer (default: 50)
offset No Query offset. Must be non-negative integer. (Default: 0)
where No The conditions for the query, corresponding to an SQL WHERE clause
join_on Only if 2 or more tables Conditions for joining multiple tables, corresponding to an SQL JOIN ON clause
order_by No The order of results, corresponding to an SQL ORDER BY clause
group_by No Field(s) on which to group results, corresponding to an SQL GROUP BY clause
having No Conditions for grouped values, corresponding to an SQL HAVING clause

Sample Code[edit]

Example 1: Basic Search[edit]

Query to see which teams faced against each other on which day.

import mwclient
site = mwclient.Site('lol.fandom.com', path='/')

response = site.api('cargoquery',
	limit = 'max',
	tables = "ScoreboardGames=SG",
	fields = "SG.Tournament, SG.DateTime_UTC, SG.Team1, SG.Team2"
)
Result
response = OrderedDict([
  ('limits', OrderedDict([('cargoquery', 500)])),
  ('cargoquery', [
    OrderedDict([
      ('title', OrderedDict([
        ('Tournament', 'All-Star 2013 Shanghai'),
        ('DateTime UTC', '2013-05-24 08:00:00'),
        ('Team1', 'China LPL'),
        ('Team2', 'North America LCS'),
        ('DateTime UTC__precision', '0')
        ]))
      ]),
    OrderedDict([
      ('title', OrderedDict([
        ('Tournament', 'All-Star 2013 Shanghai'),
        ('DateTime UTC', '2013-05-24 08:00:00'),
        ('Team1', 'North America LCS'),
        ('Team2', 'China LPL'),
        ('DateTime UTC__precision', '0')
        ]))
      ]),
    OrderedDict([
      ('title', OrderedDict([
        ('Tournament', 'All-Star 2013 Shanghai'),
        ('DateTime UTC', '2013-05-24 11:30:00'),
        ('Team1', 'Europe LCS'),
        ('Team2', 'Korea Champions'),
        ('DateTime UTC__precision', '0')
        ]))
      ]),
    ...
    ])
  ])

Example 2: Results before/after date[edit]

import mwclient
site = mwclient.Site('lol.fandom.com', path='/')

response = site.api('cargoquery',
	limit = 'max',
	tables = "ScoreboardGames=SG",
	fields = "SG.Tournament, SG.DateTime_UTC, SG.Team1, SG.Team2",
	where = "SG.DateTime_UTC >= '2019-08-01 00:00:00'" #Results after Aug 1, 2019
)

To search between Aug 8, 2019 and Aug 10, 2019 (inclusive), you can use:

where = "SG.DateTime_UTC >= '2019-08-08' AND SG.DateTime_UTC <= '2019-08-10'"

Example 3: Multiple table search[edit]

Query that returns fields from one table that are ordered based on criteria from another table.

page_to_query = "Data:2019 Mid-Season Invitational/Play-In"
response = site.api('cargoquery',
	limit = 3,
	tables = "MatchScheduleGame=MSG,MatchSchedule=MS",
	fields = "MSG.OverviewPage, MSG.MatchHistory",
	where = r'MSG._pageName="%s" AND MSG.MatchHistory IS NOT NULL AND NOT MSG.MatchHistory RLIKE ".*(lpl|lol)\.qq\.com.*"' % page_to_query,
	join_on = "MSG.UniqueMatch=MS.UniqueMatch",
	order_by = "MS.N_Page,MS.N_MatchInPage, MSG.N_GameInMatch"
)
Result
response = OrderedDict([
  ('cargoquery', [
    OrderedDict([
      ('title', OrderedDict([
        ('OverviewPage', '2019 Mid-Season Invitational/Play-In'), 
        ('MatchHistory', 'http://matchhistory.na.leagueoflegends.com/en/#match-details/ESPORTSTMNT01/1110148?gameHash=00cef136b68c8843')
        ]))
      ]),
    OrderedDict([
      ('title', OrderedDict([
        ('OverviewPage', '2019 Mid-Season Invitational/Play-In'), 
        ('MatchHistory', 'http://matchhistory.na.leagueoflegends.com/en/#match-details/ESPORTSTMNT01/1110162?gameHash=eed3d015f5f9fe83')
        ]))
      ]),
    OrderedDict([
      ('title', OrderedDict([
        ('OverviewPage', '2019 Mid-Season Invitational/Play-In'),
        ('MatchHistory', 'http://matchhistory.na.leagueoflegends.com/en/#match-details/ESPORTSTMNT01/1110177?gameHash=48acecf7e35ba59e')
        ]))
      ])
    ])
  ])

Example 4: Results in a day, joining ScoreboardGames and ScoreboardPlayers[edit]

import mwclient
import time
import datetime as dt
from datetime import date, timedelta

date="2020-01-25"
date=dt.datetime.strptime(date, "%Y-%m-%d").date()

site = mwclient.Site('lol.fandom.com', path='/')
response = site.api('cargoquery',
	limit = "max",
	tables = "ScoreboardGames=SG, ScoreboardPlayers=SP",
	join_on = "SG.UniqueGame=SP.UniqueGame",
	fields = "SG.Tournament, SG.DateTime_UTC, SG.Team1, SG.Team2, SG.Winner, SG.Patch, SP.Link, SP.Team, SP.Champion, SP.SummonerSpells, SP.KeystoneMastery, SP.KeystoneRune, SP.Role, SP.UniqueGame, SP.Side",
	where = "SG.DateTime_UTC >= '" + str(date) + " 00:00:00' AND SG.DateTime_UTC <= '" + str(date+dt.timedelta(1)) + " 00:00:00'"
)

Example 5: Save Player image[edit]

This example would let you save locally the image of a player.

import mwclient
import urllib.request
import json
import re

def get_filename_url_to_open(site, filename, player, size=None):
    pattern = r'.*src\=\"(.+?)\".*'
    size = '|' + str(size) + 'px' if size else ''
    to_parse_text = '[[File:{}|link=%s]]'.format(filename, size)
    result = site.api('parse', title='Main Page',
                      text=to_parse_text, disablelimitreport=1)
    parse_result_text = result['parse']['text']['*']

    url = re.match(pattern, parse_result_text)[1]
    #In case you would like to save the image in a specific location, you can add the path after 'url,' in the line below.
    urllib.request.urlretrieve(url, player + '.png')


player = "Perkz"

site = mwclient.Site('lol.fandom.com', path='/')
response = site.api('cargoquery',
                    limit=1,
                    tables="PlayerImages",
                    fields="FileName",
                    where='Link="%s"' % player,
                    format="json"
                    )
parsed = json.dumps(response)
decoded = json.loads(parsed)
url = str(decoded['cargoquery'][0]['title']['FileName'])
get_filename_url_to_open(site, url, player)

More Examples[edit]

For more examples, you can see River's Python code at her github page. None of this code is intended to be extended but it contains several example queries.

Possible Issues and Solutions[edit]

One common issue is that if you are querying the _pageName field, which is automatically added to every row in every table and returns the name of the page on which the row is stored, you must alias the field name, e.g. MSG._pageName=DataPage; returned field names are not allowed to begin or end with an underscore.

If one field is a List type field, you may wish to use the HOLDS condition in your where; however, this sometimes doesn't work well when you have multiple conditions specified. Also, if you are querying to return a List type field, you should append __full to the name of the field, e.g. SP.Items__full=Items instead of SP.Items=Items.

Cargo Table Overviews[edit]

You can see a full list of tables at Special:CargoTables. Note that some tables, such as [StandingsArgs], are useless out of the context of the wiki and are used only for wiki maintenance.

Player Queries[edit]

To query player information, there are three relevant tables, [Players], [PlayerRedirects], and [Disambiguations].

  • [Players] contains information about a player from {{Infobox Player}}: name, position, current team, etc. It should never be queried directly because players rename.
  • [PlayerRedirects] can be joined to [Players] on the field OverviewPage. It has one row per redirect that we have on the wiki to that player page, which will be a superset of the names the player has used in competition (sometimes common typos may also be redirected). The names here are case-insensitive and ignore special characters, so no duplication will occur when joining this between [Players] and another table.
  • [Disambiguations] will never need to be used if you have a controlled data set, but if you are taking user input you may want to query it first in case a user enters, for example, Amazing.
  • [TournamentResults] can be joined to [TournamentPlayers] to query player tournament results.

Stats Queries[edit]

The tables containing in-game stats are:

You can join them on the field UniqueGame. As with [Players], if querying a player's stats, do not query directly to this table; instead join [PlayerRedirects].

Schedule Queries[edit]

You may also want to join to [Tournaments]. The field OverviewPage is kept constant across these tables.

Team Queries[edit]

Picks and Bans Queries[edit]

To connect pick and ban from the PicksAndBansS7 table to data from other tables, such as ScoreboardGames, use the following joins:

  • PicksAndBansS7.GameID_Wiki = MatchScheduleGame.GameID_Wiki, MatchScheduleGame.ScoreboardID_Wiki = ScoreboardGames.ScoreboardID_Wiki