重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
openfootball by outsharp/shipp-skills
npx skills add https://github.com/outsharp/shipp-skills --skill openfootballopenfootball 是一个免费、开放、属于公共领域的足球数据集合。football.json 仓库为全球主要联赛和赛事提供了预构建的 JSON 文件。无需 API 密钥或身份验证。
有两种方式可以访问数据:
https://raw.githubusercontent.com/openfootball/football.json/master/{season}/{league}.json
https://openfootball.github.io/{country}/{season}/{league-name}.json
建议: 对于
football.json仓库,请使用原始 GitHub URL——它们使用简单、一致的命名约定,并且最可靠。
https://raw.githubusercontent.com/openfootball/football.json/master/{season}/{code}.json
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 组件 | 描述 | 示例 |
|---|---|---|
{season} | 赛季目录——跨年或日历年 | 2024-25, 2023-24, 2025, 2019 |
{code} | 联赛代码,格式为 {国家}.{级别} | en.1, de.1, es.1, it.1, fr.1 |
| 代码 | 联赛 | 级别 |
|---|---|---|
en.1 | 英格兰足球超级联赛 | 第 1 级别 |
en.2 | 英格兰足球冠军联赛 | 第 2 级别 |
en.3 | 英格兰足球甲级联赛 | 第 3 级别 |
en.4 | 英格兰足球乙级联赛 | 第 4 级别 |
| 代码 | 联赛 | 级别 |
|---|---|---|
de.1 | 德国足球甲级联赛 | 第 1 级别 |
de.2 | 德国足球乙级联赛 | 第 2 级别 |
de.3 | 德国足球丙级联赛 | 第 3 级别 |
| 代码 | 联赛 | 级别 |
|---|---|---|
es.1 | 西班牙足球甲级联赛 | 第 1 级别 |
es.2 | 西班牙足球乙级联赛 | 第 2 级别 |
| 代码 | 联赛 | 级别 |
|---|---|---|
it.1 | 意大利足球甲级联赛 | 第 1 级别 |
it.2 | 意大利足球乙级联赛 | 第 2 级别 |
| 代码 | 联赛 | 级别 |
|---|---|---|
fr.1 | 法国足球甲级联赛 | 第 1 级别 |
fr.2 | 法国足球乙级联赛 | 第 2 级别 |
注意: 并非所有联赛的所有赛季数据都可用。
football.json仓库会持续更新——请查看仓库以获取完整的可用文件列表。
football.json 仓库中的赛季目录可追溯到 2010-11。欧洲联赛使用跨年格式 (2024-25),而一些日历年联赛使用单年格式 (2025)。
| 格式 | 用途 | 示例 |
|---|---|---|
YYYY-YY | 欧洲俱乐部赛季(8月-5月) | 2024-25, 2023-24, 2015-16 |
YYYY | 日历年赛事 | 2025, 2020, 2019 |
已知的赛季目录:2010-11, 2011-12, 2012-13, 2013-14, 2014-15, 2015-16, 2016-17, 2017-18, 2018-19, 2019-20, 2020-21, 2021-22, 2022-23, 2023-24, 2024-25, 2025-26, 2019, 2020, 2025.
所有文件都遵循相同的 JSON 模式:
{
"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]
}
}
]
}
| 字段 | 类型 | 描述 |
|---|---|---|
name | string | 人类可读的联赛名称和赛季 |
matches | array | 比赛对象数组 |
| 字段 | 类型 | 必需 | 描述 |
|---|---|---|---|
round | string | 是 | 轮次/比赛日名称(例如,"Matchday 1", "Round of 16") |
date | string | 是 | 比赛日期,格式为 YYYY-MM-DD |
time | string | 否 | 开球时间,格式为 HH:MM(24小时制,当地时间) |
team1 | string | 是 | 主队名称 |
team2 | string | 是 | 客队名称 |
score | object | 否 | 比分对象(对于未进行的未来比赛不存在) |
status | string | 否 | 特殊状态(例如,对于行政决定的结果为 "awarded") |
| 字段 | 类型 | 描述 |
|---|---|---|
ft | [int, int] | 全场比分 [主队, 客队] |
ht | [int, int] | 半场比分 [主队, 客队](某些比赛可能没有) |
注意: 有些比赛只有
ft(全场比分)而没有ht(半场比分)。在访问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 文件是根据特定国家仓库中的纯文本 Football.TXT 源文件自动生成的:
| 仓库 | 内容 | GitHub URL |
|---|---|---|
england | 英超、英冠、英甲、英乙 | openfootball/england |
deutschland | 德甲、德乙、德丙、德国杯 | openfootball/deutschland |
espana | 西甲、西乙 | openfootball/espana |
italy | 意甲、意乙、意大利杯 | openfootball/italy |
france | 法甲、法乙 | openfootball/europe (位于 /europe 目录) |
worldcup | 国际足联世界杯(2022、2018、2014 等) | openfootball/worldcup |
euro | 欧洲杯 2024、2020、2016 等 | openfootball/euro |
champions-league | 欧冠 & 欧联杯 | openfootball/champions-league |
clubs | 俱乐部和体育场元数据 | openfootball/clubs |
world | 来自北美、亚洲、非洲、澳大利亚的联赛 | openfootball/world |
国家仓库也有自己的 GitHub Pages JSON 镜像。例如:
https://openfootball.github.io/england/2024-25/1-premierleague.json
您可以使用 fbtxt2json CLI 工具自行将 Football.TXT 源文件转换为 JSON:
# 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
GitHub 没有公布原始内容的具体速率限制,但一般准则如下:
| 准则 | 建议 |
|---|---|
| 轮询间隔 | 对同一文件的请求间隔 ≥ 60 秒 |
| 并发请求 | 保持合理(< 20 个并发) |
| 缓存 | 在本地缓存响应——数据不常更改 |
| 未经身份验证的 GitHub API | 每个 IP 每小时 60 个请求(仅适用于 API 端点,不适用于原始内容) |
提示: 由于比赛数据在比赛结束后不会改变,您可以积极缓存历史赛季。只需轮询当前赛季以获取更新。
| HTTP 状态码 | 含义 | 操作 |
|---|---|---|
| 200 | 成功 | 解析 JSON |
| 404 | 文件未找到 | 检查赛季、联赛代码或 URL 拼写 |
| 429 | 速率限制 | 退避并延迟后重试 |
| 5xx | 服务器错误 | 使用指数退避重试 |
score 字段——未来的/未进行的比赛不会有 score 字段。ht 字段——有些比赛有 ft 但没有 ht 数据。"Arsenal FC", "Manchester United FC", "Borussia Dortmund"。请使用精确的字符串匹配。"FC Bayern München"),英格兰球队使用英语名称("Arsenal FC")。status 字段很少出现——它出现在行政决定的比赛中(例如,"awarded")。time 值代表比赛举办地的本地开球时间。[主队, 客队]——score.ft[0] 始终是 team1(主队)的进球数,score.ft[1] 始终是 team2(客队)的进球数。每周安装次数
56
仓库
GitHub 星标数
3
首次出现
2026年2月22日
安全审计
安装于
github-copilot54
codex54
kimi-cli54
gemini-cli54
amp54
cursor54
openfootball is a free, open, public domain collection of football (soccer) data. The football.json repository provides pre-built JSON files for major leagues and tournaments worldwide. No API key or authentication is required.
There are two ways to access the data:
https://raw.githubusercontent.com/openfootball/football.json/master/{season}/{league}.json
https://openfootball.github.io/{country}/{season}/{league-name}.json
Recommendation: Use the raw GitHub URLs for the
football.jsonrepo — they use a simple, consistent naming convention and are the most reliable.
https://raw.githubusercontent.com/openfootball/football.json/master/{season}/{code}.json
| Component | Description | Examples |
|---|---|---|
{season} | Season directory — cross-year or calendar year | 2024-25, 2023-24, 2025, 2019 |
{code} | League code in {country}.{division} format | en.1, , , , |
| Code | League | Tier |
|---|---|---|
en.1 | English Premier League | 1st division |
en.2 | English Championship | 2nd division |
en.3 | English League One | 3rd division |
en.4 | English League Two | 4th division |
| Code | League | Tier |
|---|---|---|
de.1 | Deutsche Bundesliga | 1st division |
de.2 | 2. Bundesliga | 2nd division |
de.3 | 3. Liga | 3rd division |
| Code | League | Tier |
|---|---|---|
es.1 | Primera División (La Liga) | 1st division |
es.2 | Segunda División | 2nd division |
| Code | League | Tier |
|---|---|---|
it.1 | Serie A | 1st division |
it.2 | Serie B | 2nd division |
| Code | League | Tier |
|---|---|---|
fr.1 | Ligue 1 | 1st division |
fr.2 | Ligue 2 | 2nd division |
Note: Not all leagues are available for all seasons. The
football.jsonrepo is continuously updated — check the repository for the full list of available files.
Season directories in the football.json repo go back to 2010-11. European leagues use cross-year format (2024-25), while some calendar-year leagues use single-year format (2025).
| Format | Usage | Examples |
|---|---|---|
YYYY-YY | European club seasons (Aug–May) | 2024-25, 2023-24, 2015-16 |
YYYY | Calendar-year competitions | 2025, 2020, 2019 |
Known season directories: 2010-11, 2011-12, 2012-13, 2013-14, 2014-15, 2015-16, 2016-17, 2017-18, 2018-19, 2019-20, 2020-21, 2021-22, , , , , , , .
All files follow the same JSON schema:
{
"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 |
|---|---|---|
name | string | Human-readable league name and season |
matches | array | Array of match objects |
| Field | Type | Required | Description |
|---|---|---|---|
round | string | Yes | Round/matchday name (e.g., "Matchday 1", "Round of 16") |
date | string | Yes | Match date in YYYY-MM-DD format |
time | string | No |
| Field | Type | Description |
|---|---|---|
ft | [int, int] | Full-time score [home, away] |
ht | [int, int] | Half-time score [home, away] (may be absent for some matches) |
Note: Some matches only have
ft(full-time) withoutht(half-time). Always check for the presence ofhtbefore accessing it.
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']}")
The football.json files are auto-generated from plain-text Football.TXT source files in country-specific repos:
| Repo | Content | GitHub URL |
|---|---|---|
england | EPL, Championship, League One, League Two | openfootball/england |
deutschland | Bundesliga, 2. Bundesliga, 3. Liga, DFB Pokal | openfootball/deutschland |
espana | La Liga, Segunda División | openfootball/espana |
italy | Serie A, Serie B, Coppa Italia | openfootball/italy |
Country repos also have their own GitHub Pages JSON mirrors. For example:
https://openfootball.github.io/england/2024-25/1-premierleague.json
You can convert Football.TXT source files to JSON yourself using the fbtxt2json CLI tool:
# 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
GitHub does not publish specific rate limits for raw content, but general guidelines:
| 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 |
score before accessing — future/unplayed matches won't have a score field.ht separately — some matches have ft but no ht data."Arsenal FC", "Manchester United FC", "Borussia Dortmund". Use exact string matching."FC Bayern München"), English teams use English names ().Weekly Installs
56
Repository
GitHub Stars
3
First Seen
Feb 22, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
github-copilot54
codex54
kimi-cli54
gemini-cli54
amp54
cursor54
飞书OpenAPI Explorer:探索和调用未封装的飞书原生API接口
44,400 周安装
de.1es.1it.1fr.12022-232023-242024-252025-26201920202025Kick-off time in HH:MM format (24-hour, local time) |
team1 | string | Yes | Home team name |
team2 | string | Yes | Away team name |
score | object | No | Score object (absent for unplayed future matches) |
status | string | No | Special status (e.g., "awarded" for administratively decided results) |
france | Ligue 1, Ligue 2 | openfootball/europe (in /europe) |
worldcup | FIFA World Cup (2022, 2018, 2014, etc.) | openfootball/worldcup |
euro | Euro 2024, 2020, 2016, etc. | openfootball/euro |
champions-league | UCL & Europa League | openfootball/champions-league |
clubs | Club & stadium metadata | openfootball/clubs |
world | Leagues from N. America, Asia, Africa, Australia | openfootball/world |
"Arsenal FC"status field is rare — it appears on administratively decided matches (e.g., "awarded").time value represents the local kick-off time for the match venue.[home, away] — score.ft[0] is always the team1 (home) goals, score.ft[1] is always the team2 (away) goals.