A better Fantasy Premier League table
Me and a bunch of friends have a tradition of playing Fantasy Premier League (FPL) every season with the top 2 would get treated to dinner at the end of season social. Usually involves of fun, competitive banter in our WhatsApp group on the weekends. 😄
(TL;DR on the FPL: A management game where each user has to create a team of football players in the Premier League within a limited budget. As the players do well, they accrue points on the users’ teams that they are on.)
We use the official web app at fantasy.premierleague.com and it suffers from one major issue: we only know how well we’ve done relative to the other users at the end of the match day.
I assume this is for performance reasons given the sheer number of users and tables that they have.
Throughout the match days, to see how everyone is progressing in terms of points, we used to have keep a mental note on how many points every one got. This involved constantly going to the table page, clicking on each user, seeing how many points they got this week, etc.
Working out who captained whom and what football players each user got was also a huge pain.
This was very tedious and killed some of the flow and banter in our WhatsApp group. 😞
Then the thought occurred to me.
“Surely, I could make our own page that would live update the table throughout the day? How hard could it be? 🤔”
R & D
I started to look at how the official FPL page retrieved the data via Chrome Devtools and saw that there were a number of REST API calls being made.
Digging into the response by these APIs, they all return JSON and with relational data sets.
For example, here is the response from entry/2154506/event/16/picks
As the API URL name suggests, it returns the team player picks for a particular user and gameweek including the cost of player transfers, points accrued prior to this game week, captain and vice captain choice, etc.
The football players are identified by ‘element id’ which is related to the player data set from the API bootstrap-static. This has information such as the player’s name, their injury status and which team they are on.
After some trial and error, I’d managed to work out how which APIs I could access without needing user authorisation:
- entry/{user-id} - Information about a user such as their name
- entry/{user-id}/event/{gameweek}/picks - A user’s team player picks
- bootstrap-static - Information about players and teams
- event/{gameweek}/live - The current stats of the player such as how many points they have accrued this gameweek
- entry/{user-id}/history - History of a user and needed to get last gameweek’s scores
The league page used to not need authorisation which allowed to retrieve all the user IDs from a single league ID but that was changed last year. I now hard code the user IDs for our league into the webpage which is fine as the page is specifically for us.
Minimal Shippable
The first minimal shippable looked like this:
The user order is updated throughout the match days and username has a link to their team on official FPL site.
The high level logic was:
- Get every user’s total points from the prior weeks
- Get every user’s team picks for the current game week
- Calculate the points for each football player accrued so far this gameweek
- Apply an point modifiers such as captain choices, chips, transfers, etc
- Calculate the current score for each user
- Sort all users into a table
With the minimal version working and fulfilling our main point of frustration with the official FPL site, I excitedly uploaded the page to my website host, only to be faced with this error:
🤦♂️ It makes sense for there to be a CORS policy in policy as they would want prevent abuse from webpages like mine spamming their servers.
However, there was still hope as the API was shown to be accessible if I just entered the API address to the browser or use CURL on the commandline. Although I had made the decision earlier to not use a server due to cost, I decided to see if a Node.js server was able to access the APIs.
I did this via Glitch as I was still very new to Web Development at the time and had little exposure to the Node and NPM ecosystem.
Glitch is a fantastic free service where users can host Node.js applications for free and starts/stops instances based on their usage. It also provides an online editor which meant I didn’t have to setup my own local instance.
After fumbling my way around setting up my own REST API with the express module and accessing the FPL’s API using the request module, I was able to access the FPL’s API without CORS errors and also be able retrieve that information from my web page.
I effectively created an API ‘relay’ where all the Node.js server did was forward the data from the FPL’s API as is back to the webpage of my custom league table.
Now we are back in business! 🎉
This did come with the major drawback of having to wait for the Glitch services to start a new instance when someone accessed the webpage, but this was more than enough for now.
Feature Development
After I posted the link to the WhatsApp group, it wasn’t long before I started to get feature requests. 😅
Over several seasons (I have kids, free time is a luxury!), I started to add/remove/improve features to the page, including:
- Showing captain and vice captain choices
- Listing the whole team
- Separating the points awarded in the week from the transfer costs
- The number of players that have played so far in the game week
- What chip was played (if any)
- Showing differentials (football players not commonly chosen by the league)
- Button to quickly update the points
- Bonus point ‘predication’
Now it is possible to get almost all the information we needed on a single page, without needing to navigate across several pages. 👍
Keeping the design and layout simple was a conscious decision, with the use of font weight, colour and size for emphasis.
The important elements of information on the page are bigger and darker, such as the username and total score. Even when there is a lot of information on the page, the name of the users and total score still standout.
Details like the team picks are in a smaller font but the names of the football players, points and captain choice are in a darker colour so they are easier to pick out at a glance.
Future planned improvements will include:
- Auto substitution
- User rank changes
- Use/Find an 24/7 Node.js server
- Speed up the time it takes to make a process all the REST API calls
Closing out
This is one of my favourite side projects to work on, although it is not a large project nor my best code, it solves a problem that me and my friends have. That in itself is hugely rewarding, especially when I see them use it too in the WhatsApp group!
Enjoyed this blog post? Let me know what you think on Twitter @yaustar! 👋