How to get data from the Fantasy Premier League API

Hi everyone! I’m moving a little bit away from what I’d normally post due to there being no Fantasy Football to be played. Sad times, I know. I’ve found there is a void in my life as of late, and I still find myself looking at the /r/fantasypl subreddit regularly even though I know we’re months away from the next season starting. I’m interested in statistics and coding, which may surprise some of you!

What I’ve found from using WordPress’s own platform is that the customization which you have while using their platform inhibited me from automating processes, from using custom databases and in turn having to use plugins which just didn’t do enough for the website, in my opinion.

So enough of me complaining about the WordPress Platform and back to using the FPL API. Some of you may not know that FPL provides an API which is available for free to developers to use (or people like me who feign knowledge of web development). Let me preface this by saying I am not an excellent developer or a massively knowledgeable coder, just someone who finds this interesting and wants to help others out.

First and foremost I’ll provide you with the URLs for their API:

There are a number of other sub URLs which can be used with appending the link onto the base URL below:

Base URL:

Relative links:

  • /bootstrap (more data if authenticated)
  • /bootstrap-static
  • /bootstrap-dynamic
  • /events
  • /elements
  • /element-types
  • /fixtures
  • /teams
  • /region
  • /transfers (requires auth)
  • /entry/{entryId}
  • /entries (doesn’t work in pre-season?)
  • /my-team/{teamId} (requires auth)
  • /leagues-entered/{teamId} (requires auth)
  • /leagues-classic/{leagueId} (must be a member)
  • /leagues-classic-standings/{leagueId}
  • /leagues-h2h/{leagueId} (must be a member)
  • /leagues-h2h-standings/{leagueId}

While I understand a lot of these URLs may be useless to you, we’ll be using two of them to pull data from players from the previous season. Originally we will be using the /bootstrap-static data. From clicking the link you can firstly see a section called “phases”, which from looking at the text following relates to sections of the season:

{“id”:1,”name”:”Overall”,”start_event”:1,”stop_event”:38} – Overall showing from GW1 to GW38.

{“id”:2,”name”:”August”,”start_event”:1,”stop_event”:3} – While ID 2, with the name of August showing from GW1 to GW3.

In the next bit of data, you can see that in “elements” it is showing you information about players. Taking some of the data from ID: 1, which oddly enough is David Ospina, you can see there is a vast amount of information on players from this alone:


Some of the most important from this section includes their:





….and so on. Okay, so, I know mostly php, html, and I know a bit about APIs. So I’m going to create this using my localhost, and using their API, while making a call via php. So that means nothing to you, right? Right. So lets just do this in the most easy way possible. STEPS!

Step 1: Download and Install XAMPP.

It is really straightforward, but if you’re struggling following the steps in this youtube video. If you aren’t running Windows 10, do a similar search on Youtube. XAMPP on Linux/Apple/Windows 7/Dos. This won’t work with a Chromebook, unfortunately.

Step 2: Download a text editor

Personally, I use Sublime 3, but a lot of people use notepad++, and some madmen even use Notepad. As we’re not that mad stick to Sublime or Notepad++.

Step 3: Get Coding!

So once your text editor and your xampp is setup we’ll begin coding. First and foremost, this is going to be completely functional, as much as I like frontend development, the purpose of this is to provide people with some knowledge on how to use the API and present it on a webpage.

First off lets begin the styling, some style is needed in any site to make it look half decent. Here is the code for you first half of your document:

<!DOCTYPE html>
#player_info {
 font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
 border-collapse: collapse;
 width: 100%;

#player_info td, #player_info th {
 border: 1px solid #ddd;
 padding: 8px;

#player_info tr:nth-child(even){background-color: #f2f2f2;}

#player_info tr:hover {background-color: #ddd;}

#player_info th {
 padding-top: 12px;
 padding-bottom: 12px;
 text-align: left;
 background-color: #242424;
 color: white;


This is the code which styles the webpage. This is just basic CSS.

In “#player_info” we choose the font.

With “#player_info td, #player_info th” we add a border and padding to cells.

At “#player_info tr:nth-child(even){background-color: #f2f2f2;}” we alternate the cell’s colours.

In “#player_info tr:hover” we make the cells change colour when you hover over them.

The code “#player_info th” is used for changing the colour of the header. Simple enough. This is just to make it look nice and pretty!

Next up we call the API by using PHP! Super interesting, I know! To do this we use the file_get_contents function, which gets all the contents from a website. In this case, it is the bootstrap-static page. We have given the call a php name of $json for further referencing it.


After we call the API, we then create another variable with the name of $data and use json_decode, which takes a JSON encoded string and converts it into a PHP variable. This enables us to finish the code. A guy in work suggested me to use guzzlephp, but I’m a noob and this works, so, meh. The code beneath is as follows:

$data = json_decode($json, true);

After this, we create a table because the styling we did above would go to waste if we didn’t, and I’m not here to waste your time.

So since this API has a LOT of different sections in it I’ve filtered some of the useless ones from it and only kept the 31 columns which I feel people will find useful. Yep, only 31. Okay so now back to the code, the table’s ID matches up to the CSS, and is labeled as player_info, while <tr> stands for table row,  <th> stands for table header and <td> just stands for a standard cell in a table.

<table id ="player_info">
 <th>Web Name</th>
 <th>Player ID</th>
 <th>Full Name</th>
 <th>Current Price</th>
 <th>Value Season</th>
 <th>Cost Change from Start</th>
 <th>Percentage selected by</th>
 <th>Transfers In</th>
 <th>Transfers Out</th>
 <th>Total Points</th> 
 <th>Points Per Game</th>
 <th>Goals Scored</th>
 <th>Clean Sheets</th>
 <th>Goals Conceded</th>
 <th>Own Goals</th>
 <th>Penalties Saved</th>
 <th>Penalties Missed</th>
 <th>Yellow Cards</th>
 <th>Red Cards</th>
 <th>Bonus Points</th>
 <th>Bonus Point System Score</th>
 <th>ICT Index</th>
 <th>EA Index</th>

As you can see from the above, there are a lot of headers, some of these are useful, some not so much, personally I’ll never choose a player based off of their EA index, but some freaks might. So from this, now we get into the nitty-gritty, the really incredibly difficult part of it.

foreach($data['elements'] as $key=>$item)

In the foreach statement uses the previously encoded JSON, which was created earlier in the $data variable. From just browsing to the URL: you can see that the JSON has multiple sections which can be pulled from the JSON, so we chose the section called elements to pull our data from, as phases wouldn’t be all that useful.


Each of these elements will then be entered as a $key of an array into the variable $item. This will enable us input all of the elements into a table thanks to the foreach loop, which won’t stop until there are no more elements to enter. One thing though, is that each item has to be related back to the API, and aligned to the header.

From the boostrap link, some of the names like now_cost and code, have to be input into the echo statement so it can call the API and input it into the table. Looking at the table above you can see that the first row is <th>ID</th>, while the first row in the PHP is  <td><?PHP echo $item[‘id’]; ?></td>. The row which is just ID, can be labeled anything as there is no call code to it, but the PHP echo $item call must call an element in the API. There are also matched up with the header row, so it is good to match them up to the table headers.

The code for that is:

 <td><?PHP echo $item['id']; ?></td>
 <td><?PHP echo $item['web_name']; ?></td>
 <td><?PHP echo $item['code']; ?></td>
 <td><?PHP echo $item['first_name']; ?> <?PHP echo $item['second_name']; ?></td>
 <td><?PHP echo $item['team_code']; ?></td>
 <td><?PHP echo $item['news']; ?></td>
 <td><?PHP echo $item['element_type']; ?></td>
 <td><?PHP echo $item['now_cost']; ?></td>
 <td><?PHP echo $item['value_season']; ?></td>
 <td><?PHP echo $item['cost_change_start']; ?></td>
 <td><?PHP echo $item['selected_by_percent']; ?></td>
 <td><?PHP echo $item['transfers_in']; ?></td>
 <td><?PHP echo $item['transfers_out']; ?></td>
 <td><?PHP echo $item['total_points']; ?></td> 
 <td><?PHP echo $item['points_per_game']; ?></td>
 <td><?PHP echo $item['minutes']; ?></td>
 <td><?PHP echo $item['goals_scored']; ?></td>
 <td><?PHP echo $item['assists']; ?></td>
 <td><?PHP echo $item['clean_sheets']; ?></td>
 <td><?PHP echo $item['goals_conceded']; ?></td>
 <td><?PHP echo $item['own_goals']; ?></td>
 <td><?PHP echo $item['penalties_saved']; ?></td>
 <td><?PHP echo $item['penalties_missed']; ?></td>
 <td><?PHP echo $item['yellow_cards']; ?></td>
 <td><?PHP echo $item['red_cards']; ?></td>
 <td><?PHP echo $item['saves']; ?></td>
 <td><?PHP echo $item['bonus']; ?></td>
 <td><?PHP echo $item['bps']; ?></td>
 <td><?PHP echo $item['influence']; ?></td>
 <td><?PHP echo $item['creativity']; ?></td>
 <td><?PHP echo $item['threat']; ?></td>
 <td><?PHP echo $item['ict_index']; ?></td>
 <td><?PHP echo $item['ea_index']; ?></td>

So there it is, our PHP page which pulls every player’s data from the API and presents it in a lovely (shitty) website. The site should look something like this:


If you wish to see the repo it is available on my GitHub here: and is the fplinfo.php file. I have a few others in there which I’ve struggled with over the year, mainly due to time, heartbreaks, hangovers, teaching Shano how to use the sum function in excel, and focusing on winning my money leagues.

I guess some of you wanted to download this data? God damn you. Fine, here, I’ll add a download button so a CSV file can be downloaded. Firstly, I added a button on top to download a CSV file, which onclick enables a javascript function.

<button onclick="doCSV()"">Export HTML Table To CSV File</button>

The function doCSV() is essentially a piece of javascript which replaces the HTML table’s tags with white space and commas, as well as creating line breaks. That took longer than expected. The /g is the replace function in javascript while having commas creates comma delimiters which are required in CSV files. The \r\n is a newline and a carriage return (i.e. move the cursor to the left), which starts a new line in the CSV file.

I placed this script at the bottom of the HTML.

<script>function doCSV() {
 var table = document.getElementById("player_info").innerHTML;
 var data = table.replace(/<thead>/g, '')
 .replace(/<\/thead>/g, '')
 .replace(/<tbody>/g, '')
 .replace(/<\/tbody>/g, '')
 .replace(/<tr>/g, '')
 .replace(/<\/tr>/g, '\r\n')
 .replace(/<th>/g, '')
 .replace(/<\/th>/g, ',')
 .replace(/<td>/g, '')
 .replace(/<\/td>/g, ',')
 .replace(/\t/g, '')
 .replace(/\n/g, '');
 var mylink = document.createElement('a'); = "fplinfo.csv";
 mylink.href = "data:application/csv," + escape(data);;

So yeah… I know, you don’t wanna do all of the above. Fine, you lazy fuck.

Download the file from here by clicking this.

So, if you think this has helped in any way, or you’ve appreciated any of the content we’ve done over the last year, buy us a beer, we’re Irish, we’d appreciate it. Cheers.

[Total: 2    Average: 5/5]

11 thoughts on “How to get data from the Fantasy Premier League API

  • July 25, 2018 at 9:18 pm

    I have downloaded it, but the problem is how accurate is the above statistics ..

    And also I’m contexting in an fpl with friends in a certain fpl league any hints on players selections in other to accrue more points.. Thanks for your cooperation

    • Paddy Keogh-Goode
      July 31, 2018 at 12:36 pm

      Hi Francis, these stats are pulled exactly from the API so they’re accurate. I would always account for fixtures and have defenders which can get you clean sheets. Don’t go too heavy on certain sides as doubling up on defenders can be a bad idea, unless the side is over 50%.

  • October 16, 2018 at 4:13 pm

    This is awesome, thank you!

  • March 28, 2019 at 8:43 am

    Hey man, great content. I wanted to know if we can use the API on a separate software for peer to peer betting. thanks.

    • Paddy Keogh-Goode
      April 3, 2019 at 1:10 pm

      I don’t see why not, you’d have to read their terms and conditions

      • April 8, 2019 at 8:42 am

        Thanks for the response. How quickly do you guys get your stats updated?


Leave a Reply

Your email address will not be published. Required fields are marked *