Loading...
Loading...
openfootball (football.json) is a free, open, public domain collection of football (soccer) match data in JSON format. It covers major leagues worldwide including the English Premier League, Bundesliga, La Liga, Serie A, Ligue 1, World Cup, Euro, and Champions League. Use this skill to fetch historical and current season fixtures, results, and scores. No API key or authentication is required.
npx skill4agent add outsharp/shipp-skills openfootballhttps://raw.githubusercontent.com/openfootball/football.json/master/{season}/{league}.jsonhttps://openfootball.github.io/{country}/{season}/{league-name}.jsonRecommendation: Use the raw GitHub URLs for therepo — they use a simple, consistent naming convention and are the most reliable.football.json
https://raw.githubusercontent.com/openfootball/football.json/master/{season}/{code}.json| Component | Description | Examples |
|---|---|---|
| Season directory — cross-year or calendar year | |
| League code in | |
| Code | League | Tier |
|---|---|---|
| English Premier League | 1st division |
| English Championship | 2nd division |
| English League One | 3rd division |
| English League Two | 4th division |
| Code | League | Tier |
|---|---|---|
| Deutsche Bundesliga | 1st division |
| 2. Bundesliga | 2nd division |
| 3. Liga | 3rd division |
| Code | League | Tier |
|---|---|---|
| Primera División (La Liga) | 1st division |
| Segunda División | 2nd division |
| Code | League | Tier |
|---|---|---|
| Serie A | 1st division |
| Serie B | 2nd division |
| Code | League | Tier |
|---|---|---|
| Ligue 1 | 1st division |
| Ligue 2 | 2nd division |
Note: Not all leagues are available for all seasons. Therepo is continuously updated — check the repository for the full list of available files.football.json
football.json2010-112024-252025| Format | Usage | Examples |
|---|---|---|
| European club seasons (Aug–May) | |
| Calendar-year competitions | |
2010-112011-122012-132013-142014-152015-162016-172017-182018-192019-202020-212021-222022-232023-242024-252025-26201920202025{
"name": "English Premier League 2024/25",
"matches": [
{
"round": "Matchday 1",
"date": "2024-08-16",
"time": "20:00",
"team1": "Manchester United FC",
"team2": "Fulham FC",
"score": {
"ht": [0, 0],
"ft": [1, 0]
}
}
]
}| Field | Type | Description |
|---|---|---|
| string | Human-readable league name and season |
| array | Array of match objects |
| Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | Round/matchday name (e.g., |
| string | Yes | Match date in |
| string | No | Kick-off time in |
| string | Yes | Home team name |
| string | Yes | Away team name |
| object | No | Score object (absent for unplayed future matches) |
| string | No | Special status (e.g., |
| Field | Type | Description |
|---|---|---|
| | Full-time score |
| | Half-time score |
Note: Some matches only have(full-time) withoutft(half-time). Always check for the presence ofhtbefore accessing it.ht
curl -s "https://raw.githubusercontent.com/openfootball/football.json/master/2024-25/en.1.json" | jq .import requests
url = "https://raw.githubusercontent.com/openfootball/football.json/master/2024-25/en.1.json"
data = requests.get(url).json()
print(f"League: {data['name']}")
print(f"Total matches: {len(data['matches'])}")
for match in data["matches"][:10]:
ft = match.get("score", {}).get("ft")
if ft:
print(f" {match['date']} {match['team1']} {ft[0]}-{ft[1]} {match['team2']}")
else:
print(f" {match['date']} {match['team1']} vs {match['team2']} (no score)")import requests
from collections import defaultdict
url = "https://raw.githubusercontent.com/openfootball/football.json/master/2024-25/en.1.json"
data = requests.get(url).json()
table = defaultdict(lambda: {"played": 0, "won": 0, "drawn": 0, "lost": 0,
"gf": 0, "ga": 0, "points": 0})
for match in data["matches"]:
score = match.get("score", {}).get("ft")
if not score:
continue
t1, t2 = match["team1"], match["team2"]
g1, g2 = score
for team, gf, ga in [(t1, g1, g2), (t2, g2, g1)]:
table[team]["played"] += 1
table[team]["gf"] += gf
table[team]["ga"] += ga
if gf > ga:
table[team]["won"] += 1
table[team]["points"] += 3
elif gf == ga:
table[team]["drawn"] += 1
table[team]["points"] += 1
else:
table[team]["lost"] += 1
# Sort by points, then goal difference
sorted_table = sorted(table.items(),
key=lambda x: (x[1]["points"], x[1]["gf"] - x[1]["ga"]),
reverse=True)
print(f"{'Team':<35} {'P':>3} {'W':>3} {'D':>3} {'L':>3} {'GF':>4} {'GA':>4} {'GD':>4} {'Pts':>4}")
print("-" * 70)
for i, (team, stats) in enumerate(sorted_table, 1):
gd = stats["gf"] - stats["ga"]
print(f"{i:>2}. {team:<32} {stats['played']:>3} {stats['won']:>3} "
f"{stats['drawn']:>3} {stats['lost']:>3} {stats['gf']:>4} "
f"{stats['ga']:>4} {gd:>+4} {stats['points']:>4}")import requests
url = "https://raw.githubusercontent.com/openfootball/football.json/master/2024-25/en.1.json"
data = requests.get(url).json()
team = "Arsenal FC"
matches = [m for m in data["matches"]
if team in (m["team1"], m["team2"]) and m.get("score", {}).get("ft")]
for m in matches:
ft = m["score"]["ft"]
opponent = m["team2"] if m["team1"] == team else m["team1"]
venue = "H" if m["team1"] == team else "A"
my_goals = ft[0] if m["team1"] == team else ft[1]
opp_goals = ft[1] if m["team1"] == team else ft[0]
result = "W" if my_goals > opp_goals else ("D" if my_goals == opp_goals else "L")
print(f" {m['date']} ({venue}) {result} {my_goals}-{opp_goals} vs {opponent}")import requests
leagues = {
"Premier League": "en.1",
"Bundesliga": "de.1",
"La Liga": "es.1",
"Serie A": "it.1",
"Ligue 1": "fr.1",
}
season = "2024-25"
base = "https://raw.githubusercontent.com/openfootball/football.json/master"
for name, code in leagues.items():
url = f"{base}/{season}/{code}.json"
resp = requests.get(url)
if resp.status_code == 200:
data = resp.json()
total = len(data["matches"])
played = sum(1 for m in data["matches"] if m.get("score", {}).get("ft"))
print(f"{name}: {played}/{total} matches played")
else:
print(f"{name}: not available for {season}")const url = "https://raw.githubusercontent.com/openfootball/football.json/master/2024-25/en.1.json";
const res = await fetch(url);
const data = await res.json();
console.log(`League: ${data.name}`);
console.log(`Matches: ${data.matches.length}`);
data.matches.slice(0, 10).forEach((m) => {
const ft = m.score?.ft;
if (ft) {
console.log(` ${m.date} ${m.team1} ${ft[0]}-${ft[1]} ${m.team2}`);
}
});# Get all results for a specific team
curl -s "https://raw.githubusercontent.com/openfootball/football.json/master/2024-25/en.1.json" \
| jq -r '.matches[]
| select(.team1 == "Liverpool FC" or .team2 == "Liverpool FC")
| select(.score.ft)
| "\(.date) \(.team1) \(.score.ft[0])-\(.score.ft[1]) \(.team2)"'import requests
url = "https://raw.githubusercontent.com/openfootball/football.json/master/2024-25/en.1.json"
data = requests.get(url).json()
team_a = "Arsenal FC"
team_b = "Liverpool FC"
h2h = [m for m in data["matches"]
if {m["team1"], m["team2"]} == {team_a, team_b}
and m.get("score", {}).get("ft")]
for m in h2h:
ft = m["score"]["ft"]
ht = m["score"].get("ht", ["?", "?"])
print(f"{m['date']}: {m['team1']} {ft[0]}-{ft[1]} {m['team2']} (HT: {ht[0]}-{ht[1]})")import requests
base = "https://raw.githubusercontent.com/openfootball/football.json/master"
seasons = ["2022-23", "2023-24", "2024-25"]
team = "Manchester City FC"
all_results = {"W": 0, "D": 0, "L": 0, "GF": 0, "GA": 0}
for season in seasons:
resp = requests.get(f"{base}/{season}/en.1.json")
if resp.status_code != 200:
continue
data = resp.json()
for m in data["matches"]:
ft = m.get("score", {}).get("ft")
if not ft:
continue
if m["team1"] == team:
gf, ga = ft
elif m["team2"] == team:
ga, gf = ft
else:
continue
all_results["GF"] += gf
all_results["GA"] += ga
if gf > ga:
all_results["W"] += 1
elif gf == ga:
all_results["D"] += 1
else:
all_results["L"] += 1
print(f"{team} across {', '.join(seasons)}:")
print(f" W{all_results['W']} D{all_results['D']} L{all_results['L']}")
print(f" Goals: {all_results['GF']} scored, {all_results['GA']} conceded")# Find all matches with 5+ total goals in the Premier League 2024/25
curl -s "https://raw.githubusercontent.com/openfootball/football.json/master/2024-25/en.1.json" \
| jq -r '.matches[]
| select(.score.ft)
| select((.score.ft[0] + .score.ft[1]) >= 5)
| "\(.date) \(.team1) \(.score.ft[0])-\(.score.ft[1]) \(.team2) (Total: \(.score.ft[0] + .score.ft[1]))"'import requests
url = "https://raw.githubusercontent.com/openfootball/football.json/master/2024-25/en.1.json"
data = requests.get(url).json()
matchday = "Matchday 38"
matches = [m for m in data["matches"] if m["round"] == matchday]
print(f"--- {matchday} ---")
for m in matches:
ft = m.get("score", {}).get("ft")
if ft:
print(f" {m['date']} {m.get('time', '')} {m['team1']} {ft[0]}-{ft[1]} {m['team2']}")
else:
print(f" {m['date']} {m.get('time', '')} {m['team1']} vs {m['team2']}")football.json| Repo | Content | GitHub URL |
|---|---|---|
| EPL, Championship, League One, League Two | openfootball/england |
| Bundesliga, 2. Bundesliga, 3. Liga, DFB Pokal | openfootball/deutschland |
| La Liga, Segunda División | openfootball/espana |
| Serie A, Serie B, Coppa Italia | openfootball/italy |
| Ligue 1, Ligue 2 | openfootball/europe (in |
| FIFA World Cup (2022, 2018, 2014, etc.) | openfootball/worldcup |
| Euro 2024, 2020, 2016, etc. | openfootball/euro |
| UCL & Europa League | openfootball/champions-league |
| Club & stadium metadata | openfootball/clubs |
| Leagues from N. America, Asia, Africa, Australia | openfootball/world |
https://openfootball.github.io/england/2024-25/1-premierleague.jsonfbtxt2json# Convert a single league file
fbtxt2json england/2025-26/1-premierleague.txt -o en.1.json
# Convert an entire country repo at once
fbtxt2json . -o ./_site| Guideline | Recommendation |
|---|---|
| Polling interval | ≥ 60 seconds between requests for the same file |
| Concurrent requests | Keep reasonable (< 20 concurrent) |
| Caching | Cache responses locally — data changes infrequently |
| Unauthenticated GitHub API | 60 requests/hour per IP (only applies to API endpoints, not raw content) |
Tip: Since match data doesn't change after a game is completed, you can aggressively cache historical seasons. Only poll the current season for updates.
| HTTP Status | Meaning | Action |
|---|---|---|
| 200 | Success | Parse the JSON |
| 404 | File not found | Check the season, league code, or URL spelling |
| 429 | Rate limited | Back off and retry after a delay |
| 5xx | Server error | Retry with exponential backoff |
scorescorehtftht"Arsenal FC""Manchester United FC""Borussia Dortmund""FC Bayern München""Arsenal FC"status"awarded"time[home, away]score.ft[0]team1score.ft[1]team2