no saudi pro league

Thu, August 31, 2023 by Daniel
i won't offer saudi pro league.

v4 release

Fri, May 20, 2022 by Daniel
Almost 4 years after publishing the football-data API v2, today v4 sees light of day.
I decided to make some breaking changes and do a fresh v4 release and here we go. The main goals set for v4 were:
  • flatten data structures
  • improve consistency across resources
  • improve expressiveness
  • add control to response sizes by selectively unfolding specific nodes
  • review/rewrite entire documentation
  • remain as backward compatible as possible
I also used the upgrade to refactor code, upgrade to the latest versions of the software I use and move the server farm to a new provider.

Last but not least the API is more frontend-aware now, as I stumbled over several shortcomings while building on top of it, so I directly tackled them.

In the end I can say that I really like what I built, and I hope so do you.


World Cup 2022 - Qatar

Sat, April 2, 2022 by Daniel
It's all there :-)
So you can start building your WC project right away...

Calculate homewin percentage

Tue, December 29, 2020 by Daniel
I recently read some articles stating that the home advantage decreased during COVID-19 times. Utilizing the API I created this linechart which pretty much confirms these articles - at least the data for the top European leagues.

Use the python code below to create such linecharts by yourself:

import matplotlib
import matplotlib.pyplot as plt
import requests
import json

def get_home_wins_for_competition(competition_code):
    base_uri = '' + competition_code + '/matches'
    headers = { 'X-Auth-Token': 'YOUR_TOKEN_HERE', 'Accept-Encoding': '' }
    retVal = []
    seasons = [str(x) for x in range(2010,2020)]
    for year in seasons:
      uri = base_uri + "?season=" + str(year)
      response = requests.get(uri, headers=headers)
      matches = response.json()['matches']
      home_wins = 0; match_counter = 0;
      for m in matches:
        if (m['score']['winner'] == "HOME_TEAM"):
          home_wins += 1
        if (m['score']['winner'] is not None and m['score']['winner'] != "DRAW"):
          match_counter += 1
      retVal.append(round((home_wins/match_counter)*100, 2))

    return retVal

competitions = ['BL1', 'PL', 'PD', 'SA', 'FL1', 'DED']
seasons = [str(x) for x in range(2010,2020)]
values = {}

for key in competitions:
    values[key] = get_home_wins_for_competition(key)

plt.ylabel('% of home wins')
plt.ylim(40.0, 70.0)

for key in competitions:
    plt.plot(seasons, values[key], label = key)

plt.suptitle('less home wins during covid')

Added Odds to match resource

Wed, February 26, 2020 by Daniel
Hello everyone, last days I added average post-match odds to the matches endpoints. To demonstrate it's usage see the python code below. It fetches all matches (of your plan) for today, iterates over all of them and saves the hightest odds for each homeWin, awayWin and draw and finally prints them.

# @date 2020/02/25
# @author daniel (

import requests
import json
import time

uri = ''
headers = { 'X-Auth-Token': 'YOUR_KEY_HERE', 'Accept-Encoding': '' }

response = requests.get(uri, headers=headers)
upcoming_matches = response.json()['matches']

highest_odds = {"homeWin": 0.0, "draw": 0.0, "awayWin": 0.0}
matches = {"homeWin": None, "draw": None, "awayWin": None}

for m in upcoming_matches:
      if m['odds']['homeWin'] is not None and m['odds']['homeWin'] > highest_odds['homeWin']:
        highest_odds['homeWin'] = m['odds']['homeWin']
        matches['homeWin'] = m
      if m['odds']['draw'] is not None and m['odds']['draw'] > highest_odds['draw']:
        highest_odds['draw'] = m['odds']['draw']
        matches['draw'] = m
      if m['odds']['awayWin'] is not None and m['odds']['awayWin'] > highest_odds['awayWin']:
        highest_odds['awayWin'] = m['odds']['awayWin']
        matches['awayWin'] = m
  except KeyError as e:
      print('You need to enable Odds in User-Panel.')

print("Highest odds for upcoming games today for home win, draw and away win are as follows:\n")
print("homeWin: " + matches['homeWin']['homeTeam']['name'] + " against " + matches['homeWin']['awayTeam']['name'] + " (" + str(highest_odds['homeWin']) + ")")
print("draw: "  + matches['draw']['homeTeam']['name'] + " against " + matches['draw']['awayTeam']['name'] + " (" + str(highest_odds['draw']) + ")")
print("awayWin: " + matches['awayWin']['homeTeam']['name'] + " against " + matches['awayWin']['awayTeam']['name'] + " (" + str(highest_odds['awayWin']) + ")")


Simple calcs and happy new year!

Thu, January 10, 2019 by Daniel
Happy new year to everyone!
Recently I watched a show on television where the guys talking tried to find reasons why there are so many goals in this years' season of the Bundesliga. I actually wasn't aware of that but these days I thought I'll prove that and see how easy/difficult that is by utilizing my own API.
Actually it was pretty straightforward using the python script below, which I don't want to hold back from you:
# Small python script to prove a TV hosts' statement of like
# 'Why is it, that this year there are loads of goals scored?'
# @date 2018/12/28
# @author daniel (

import requests
import json

for year in range(2018, 2016, -1):
    uri = '' + str(year)
    headers = { 'X-Auth-Token': 'YOUR_TOKEN_HERE' }
    response = requests.get(uri, headers=headers)
    matches = response.json()['matches'] 
    #finishedMatches = filter(lambda match: match['status'] == 'FINISHED', matches)
    matchesUntilMatchdayX = filter(lambda match: match['matchday'] < 18, matches)

    totalGoals = 0
    for match in matchesUntilMatchdayX:
      totalGoals += match['score']['fullTime']['homeTeam'] + match['score']['fullTime']['awayTeam']

    print "Total goals scored in season " + str(year) + ": " + str(totalGoals)
    print "   That is an avg of " + str(round((float(totalGoals) / 18.0),2)) + " per matchday."
    print "   and an avg of " + str(round((float(totalGoals) / len(matchesUntilMatchdayX)),2)) + " per game."

Don't forget to insert your own token and feel free to play around with it; e.g. use "PL" to see same statistics for the Premiere League or change the matchday in the lamba expression to see results for different sections of the season.


BTW: He was right :-)

Added limit filter to matches subresource

Thu, October 4, 2018 by Daniel
Hey fellows,
just a quick note: I added the limit filter to the team matches subresource, so if your programming language is lacking a head() or first() function on lists/collections, you can now easily get the latest match of your favourite team by firing:

Or the next upcoming match respectively:


Codes for Competitions back

Tue, August 28, 2018 by Daniel
Hi guys,
I'm very happy to announce that I added values to the code-attribute of the competition resource back again (formerly known as leagueCodes).
They are back now and even more powerful as you can even use them now as identifier, e.g. by firing
you will always receive the matches for the active season of the English Premier League, without even touching your code. So your clients will run and run and run, season for season for season... (note that this is not yet possible on the matches main resource, this will take some days to be implemented),BL1&status=FINISHED&dateFrom=2018-10-01&dateTo=2018-10-08
responds with all finished games from 1st to 8th of october for English Premier League and German Bundesliga.

Additionally I added back the crestUrl attribute to the team (sub)resources and the standings. I also cumulated it to be named "crestUrl"; v1 was mixing this up over the different resources.


PHP-Lib updated

Fri, August 10, 2018 by Daniel
Hi there,
I finally updated the small PHP code that shows basic functions of the API. You can have a look at it here:

On matches and status

Tue, July 17, 2018 by Daniel
Hi there,

with v2 matches have more fine grained status. See the status diagram below.

A match always starts with status "SCHEDULED". There is no TIMED status any more, so the regular workflow is a status change to IN_PLAY, to PAUSED, to IN_PLAY (again) and to FINISHED.

Take notice that there is a 'superior' status LIVE, that does not exist as a status per se, but you can use it in the matches resource as a filter. So you get all matches back that are currently IN_PLAY or PAUSED, thus LIVE :-)

AWARDED is also a new status as at times games find it's final result legally afterwards and mostly end 3 to 0 for one team then. Hope this is all clear and makes sense.


Finally - Football-Data API v2

Thu, June 28, 2018 by Daniel

Though Germany just got kicked out of the World Cup I'm very proud to announce, that v2 is finally online! It’s the biggest update of the API since I’ve started the project in 2014.

The top competitions will remain free in the new API. What was free in v1, remains free in v2 and will remain free forever!

The extra data/competitions are available under 3 new paid plans: Standard (25 competitions/€49 per month), Advanced (50 competitions/€99 per month) and Pro (144 competitions/€249 per month). These paid plans will help to support this project and fuel the development and growth of the API.

What’s new in v2?
  • 144 competitions (leagues & cups) are now available through the API
  • Live scores available for all matches
  • Match fixtures are now updated every hour (instead of every day)
  • League tables; Home/Away tables
  • Match lineups and substitutes
  • Goal scorers and assists
  • Bookings (Yellow Cards, Red Cards)
  • Team squads

There will be further updates in the upcoming days and weeks, so keep an eye on this blog to follow the latest changes.

If you have any questions, please contact me at daniel at


World Cup ahead

Fri, December 1, 2017 by Daniel
Hi everyone, it's already there :-)
Besides maintaining the current data and API I'm working on a new release, v2 - hopefully including all proposals / feature requests of the last years. The release will be accompanied by a facelift of the frontend and find it's way to the public in March 2018. With new stuff to come other things will fade. That is alpha version which served faithfully millions of requests. Additionally support for the Event API is still stalled at the moment.
best, daniel

Major platform upgrade

Sun, April 16, 2017 by Daniel
Hi folks, I'm proud to announce a major upgrade to the API which - you most likely won't recognize :-) I upgraded the operating system, increased hardware resources and on top of that finally migrated to the latest grails release running on Java 8. As there were major changes in the architecture I rewrote almost the entire codebase but now everything looks much cleaner and hopefully is prepared for the future. I even decided to setup a status page, so you have another way to track down errors (exclude API availability). I hope DNS change and firewall rules in the transition period work properly and no downtime will occur. To the end of 2017, alpha version is gonna be shut down. I will get in touch with these 'nostalgic' ;-) users separately via mail to discuss the necessary steps to upgrade to v1. So from 2018 on, all requests to alpha version will be redirected to v1 and thus just in cases produce slighly different responses than expected, so in most cases it will suffice to just change the URI. Besides I just recognize that I did not blog too much the last year :-) However, the project is not dead, it's more that I shifted communication towards good old email. Now that the upgrades are done, I can focus on a new release that unifies alpha, v1 and all my experiences and user feedback in v2. best, daniel


Thu, February 18, 2016 by Daniel
My hosting provider just told me that there will be downtimes this evening from 9pm until tomorrow 3am CET. These downtimes will be as short as possible but as it sounds there are two reboots of the host system. I hope all services startup again cleanly. best, daniel

things going on...

Sun, February 14, 2016 by Daniel
hi there, the last few weekends I started running the refactored twitter bot in production. In the beginning that was still way buggy, so I just let it run with eye-control. There were some little irregularities which I hope did not affect your software too much. However, meanwhile it's running pretty stable and promising. I implemented some superior backend based on elasticsearch where you can like throw anything at and it tries to parse the data into my structures. I'm capturing like 70-80% I'd say of all fixtures, in case you wonder why there are some games updated slower than others. You can find more about the implementation and operation details soon in an extra article here. Moreover the refactoring of the realtime data is almost finished, it became the Event-API. and you can find a short guide on it's functionality and how to set it up again - soon. So stay stuned :) best, daniel.

European Championships online.

Mon, December 14, 2015 by Daniel
hi there, for the impatient: :-) best, daniel.

PHP library

Wed, November 25, 2015 by Daniel
hi there, I've just put up a library that implements some functionalities of the API and showcases it's usage. It's neither complete, nor an eye catcher, but it's working :) You're welcome to extend the library and open a pull request. Setup a webserver, clone the repo from the underneath URI and call index.php to see it in action. best, daniel.

official release of v1 the 2015/12/03.

Wed, November 11, 2015 by Daniel
Okay I'm already a few month late, but due to nostalgic reasons I decided to 'officially' release v1 the 3rd of december due to the fact that that same day in 2014 the registration form and with it vital features of the API as it's running in alpha state right now were relased. However, 'unofficially' v1 is already there and the impatient can play around with it, actually the links on the landing page are already pointing to the new version as the on-site-docs do. The base URI now reads (as you might have expected): Most likely you won't spot too much changes at first glance. However, I'm still completing documentation and writing more samples that will showcase the new features. If you don't want to migrate (too soon) and you (currently think) you do not need new features you can stay calmed though: alpha version will keep running indefinitely. best, daniel.

small update: API outage on 15th of august.

Sun, August 16, 2015 by Daniel
hi there, due to a hardware breakdown of my provider all API services were down yesterday from around 9am to 3pm. Sorry for the inconvenience. Meanwhile v1 release is more or less done, some further testing but seems releasing to the end of august should be possible without problems. More on the features in a blog post accompanying the release. best, daniel.

Small update

Sun, July 5, 2015 by Daniel
hi there, as new seasons' schedules slowly but surely getting public I integrated those available, others will follow. Development of v1 still in progress and I hope I can stick to my self-imposed schedule. I'll keep you posted! best, daniel.

Almost the end of the season: further roadmap

Thu, April 23, 2015 by Daniel
lots of you guys not just ask about a desired feature but keep asking about a (strategic) roadmap of the API, so let me touch that topic and give you some information what you can expect in the future. In August 2015 version 1 of the API or short "v1" will be released. After almost 2 years of running beta and alpha versions successfully, I'm glad to offer the first version that is also stable in it's name. As far as I can tell by now it won't get too much new features (thus, most likely will be fully backwards compatible to alpha), but will merge the best features of beta and alpha version, e.g. you will be able to switch from concise to expressive output. But more on the (final) features will be announced in the documentation. Mostly invisible to endusers but very important for me is that with v1 I will finally switch to a new platform and the API will finally be upgraded to Java 7. That will involve major refactorments as well, as Java 7 acts differently in terms of date or regex operations. As mentioned earlier the API emerged out of a privat project which is why the majority of the team names is german. This will change as after the last game for season 2014 was played all team names will get standardized to english. I intent to move the homepage to Hugo (slowly but surely I need pagination for that blog...) and upgrade the documentation to Asciidoctor, just to mention some cosmetic changes as well :) Another question that's raised very often is if the API really is and will continue being free. Actually the answer is yes but it depends, because it's only free for non-commercial use. If you use the data commercially, please get in contact with me, so we find a fair-minded solution that pleases both of us. Besides I can give you important background information on how the API 'ticks' internally so you can optimize your integration and last but not least I'll offer you some additional advanced endpoint functions to make the API fit seamlessly with your existing data. Last but not least I want to add a FAQ site, extend the code samples and also add some client libraries but I gotta see how much time is left. In the end, this blog post answers another often asked question in itself: Will this API remain online and will I keep supporting it and the definite answer is: absolutely! daniel.

Small udpate: direct date usage

Tue, March 24, 2015 by Daniel
I extended the usage of timeframe based requests as you now can specify the dates directly. Just set the two parameters timeFrameStart and timeFrameEnd to a date in the format yyyy-MM-dd. So e.g. a request to show all games of the first 5 days of march looks like that: All resources that support the timeFrame-Filter now also support these two filters (that always must be used together). daniel.

New feature: realtime scores

Mon, February 16, 2015 by Daniel
Frequently I was asked if I also plan to offer livescores. At first I did not want that, I never intended the API to offer that kind of data. I think a RESTful architecture is not really suitable for distributing (near) real-time information. However that question remained and I couldn't forget about it. So I did some research if it's somehow possible and when I found out it actually is, I decided to try it out and there we go. At first I asked myself what livescores really are. How live do they have to be? I found out that livescores advertised mostly aren't that live. Websites pretending to offer livescores show a goal 2 minutes later than I could see it on television. That's not my definition of live. And because I want to express that by live I understand the freshest data possible I want to distance myself from that widespread livescores. And that's why I wont' offer live, but realtime scores. And what's so wrong about REST and realtime data? Actually it's the protocol, that is HTTP. Let me back that up. Remember the Champions League final 2012? Chelsea was playing some kind of Catenaccio and Munich was simply not able to crack the defence until the 83th minute, when Müller scored a header. Drogba striked back and then there was extra time and frequent action in terms of goals. However, what would have happened technically? Well actually the first 83 minutes our RESTful application had to ask every minute for updated data. So at least one request every minute, makes up to 83 requests. Some guys maybe coded some nice Comet or Web Sockets and want to be even "more live" and decide to poll 3 times the minute. That makes around 250 requests - for nothing but the information that nothing happened. So it seems we're wasting resources and that's caused by architecture. So what to do? One solution is the use of callbacks. A client tells the server a callback endpoint and the server acknowledges it's reception. So to stick to our example nothing happens until the 83th minute where the server requests the callback and thus notifies the client about something happened. We saved 250 requests, so that should do it. In fact I considered that solution but it has the drawback in that the client has to switch roles and implement server functionality and the same but vice versa applies for the server. Twitter provides another solution with their Streaming API. They use regular HTTP but unlike closing the connection after sending data, they keep it alive and resend data upon arrival. That works as well but actually I don't see any reason why one should stick to HTTP. I think HTTP simply wasn't designed for such use cases and thus shouldn't be misused for. So to cut a long story short I decided to implement a solution based on AMQP, a binary protocol. Or to be precise I implemented a solution that combines REST and AMQP and I wonder that I couldn't find one API that does that as well and already. Well if there is something fundamentally wrong, I'll find out. Have a look at the setup guide for realtime data to see how to implement that in your application. daniel.

new attribute: status on fixture resource.

Tue, February 3, 2015 by Daniel
I added some basic code examples for beginners to the documentation section. Basically I wanted to answer FAQs that often come in via mail and test a syntax highlighter for some more advanced code examples to follow, as I'm proud to announce that I'll finally add live near-realtime scores. I'm planning to release a first prototype with the round of the last 16 of the Champions League, which takes place the 17th of February. As I'm gonna watch the games anyways it won't be much of a problem to input the data by hand and test how and if my imagined design will work out. Stay tuned to get instructions the next days on how to participate in testing. Mentioning design I also came up with this state diagram for the status field of the fixture resource. Guess it's pretty self-explanatory except the difference between SCHEDULED and TIMED, which is because fixtures typically first get scheduled (that is: get a rough date (range) it will be played) but get timed (that is: get an exact date and time it will be played) much later. For instance fixtures of the Bundesliga are typically scheduled once a year and about 6 weeks before the scheduled date, when officials know when and who will play european games, they get timed. daniel.

why one should use

Wed, January 28, 2015 by Daniel
Though I state in the about section that I cannot guarantee the data to be accurate, accuracy is the answer. Recently the 20th matchday of the Premiere League catched my attention. Chelsea and ManCity were precisely equal in all terms, though BBC, The Guardian, Sky Sports and even the official Premiere League page itself state Chelsea is ranked on top while ManCity only owns 2nd place. Though I don't think this was on purpose but on the fact that a default order sorts C before M, this issue remains unfair and if I trust this wikipedia link it's simply wrong: Teams are ranked by total points, then goal difference, and then goals scored. If still equal, teams are deemed to occupy the same position. Maybe these guys should rely on data of ;-) See my League Table of the 20th matchday, which does not disadvantage anyone but places teams according to the rules. daniel.

alpha online.

Sun, January 18, 2015 by Daniel
So that's it, alpha is online. Few days ago I linked the resources on the landing page to the new versioned release alpha. I don't wanna explain or talk too much here about the features as you can read everything in the documentation. Unfortunately not so nice requests where I couldn't figure out any sense behind increased rapidly, so I had to implement throttling. I did not design it that much and most likely it will change, but for the first shot everyone is limited to 15 requests per minute which is like 900 requests per hour. Update: See the documentation for the rate limit convenctions. If that hinders your current implementation immensively, contact me as it's possible to set more gentle limits for certain authentication token. Next steps are to put some code samples to the documentation and maybe publish a roadmap. But before that I'll take a short break and review everything there is so far. so long, daniel.

alpha on track.

Tue, January 6, 2015 by Daniel
hi there and a happy new year! Just want to drop a line that alpha version is on track and will be released the 18th of January. The implementation is almost complete, just some tests and documentation need to be finalized. In short a few appetizers: introduced versioning. you get access to football data down to 2005, useful for statistical analyzes. the resources are better linked and more talkative, holding more information. I added the Champions League (to beta version as well and already). I improved the process of updating results. Notice that I did a data cleanup as well and the league shortcuts changed from lower to uppercase. I don't think alpha is perfect at all (which is why it's alpha and not v1), but I think it's already much better than beta. It ran for almost a year now and likely will further run for another, but won't get any updates or changes any more. I think it's no problem to change evolve an API as long as the changes are backwards compatible and don't break clients. So I'm gonna work only on alpha from now on. daniel.

Major upgrades.

Wed, December 3, 2014 by Daniel
I finally managed to add some kind of design to the page. It's not my strength, but I guess it's way better than before. So enjoy it :) Besides I added the possibility to access the API using an authentication token. Click on Free API Key in the menu for more information. The resources itself did not change, nor did the filters. Well at least not yet. Thanks a lot for all your feedback, I'm trying to merge all your suggestions in perfect endpoints, but as requirements differ immensely I cannot satisfy everyone's needs completely. Anyway I have some neat ideas in mind that will be transformed into code until next year. I guess the API is then finally ready to lose beta status and get stamped stable :) daniel.

Small updates.

Mon, November 17, 2014 by Daniel
I added better error handling to the API, so now you get meaningful hints on why requests failed or did not respond like you expected. Moreover I changed the structure of the ranking subresource which now holds the matchday but not the needless array around the position-objects any more. As the JSON-viewer for FF did not show me that error in the response, I switched to the REST Easy plugin which is a good alternative. Still thinking about versioning and introducing a (free) API-key for usage. Planning on releasing these upgrades to the beginning of the new year. I'll keep you posted! daniel.

introducing the timeframe argument

Mon, October 13, 2014 by Daniel
I wasn't happy with the 'upcoming' and 'past' URIs, as neither upcoming nor past were (sub)ressources, but their appearance in the URI made them appear like that. Also some good feedback of you guys concerning the way to retrieve upcoming games made me re-think this whole thingy and I came up with the subsequent solution. The URIs vanished completely and their intent turned into the timeFrame argument. Actually you cannot request a number of past/upcoming games any more, but you can define a timeFrame to display fixtures in. For instance, if you'd like to get all completed games of the last two weeks for a certain team you'd do a GET to /team/22/fixtures/?timeFrame=p14. To retrieve all games of all available leagues in the next 4 days, you'd GET to /fixtures/?timeFrame=n4. I hope you grasp the idea. I think this is a pretty handy solution and I guess you're now way more flexible in building applications to your needs. btw: The 'old' URIs still work due to compatiblity but are not documented any more. (which reminds me to introduce some kind of versioning) cheers daniel.

small pragmatism change: pluralization

Thu, October 9, 2014 by Daniel
I decided to change all URIs to plural. So /soccerseason is now /soccerseasons and so on. This from now on applies for all (sub)ressources, though - as always - the old URIs will still work for compatibility issues but are not documented any more. cheers daniel.

new resource: fixture

Wed, September 10, 2014 by Daniel
I decided to introduce 'fixture' also as a main ressource to be able to pull upcoming fixtures across all leagues easily. You can filter by days, so if you wanna see all upcoming features for all leagues, you'd GET to /fixture/upcoming?days=2. I really had to think about that and hope it does not puzzle you as 'fixture' is now a subressource for team and socceseason but also a main ressource. cheers daniel.

let the games begin.

Mon, August 25, 2014 by Daniel
The major leagues are imported and get their updates every night. Any league missing? Drop me a note and I'll see if I can add it quickly. Besides it's now possible to filter the fixture ressource. I implemented a venue filter and the long planned count filter; so you can now specify the number of games returned so you can only return those games that e.g. took place in the home stadium. Keep me posted for desired features, API stability and you know - feedback. cheers daniel.

content update for new seasons data.

Wed, July 16, 2014 by Daniel
Hi all u football associates out there :)
Actually I'm doing an initial import of all the new seasons' data at the moment. You can expect all data to be complete to the end of july. As you can see, moreover I decided to add a small blog section to keep you posted about important changes, explain features, best practices, hints and so on.