Free API and MCP server
Everything on FootballAPIs — prices, free plans, leagues and data types for 17 football data APIs — as free, read-only JSON, and as an MCP server your AI assistant can ask directly.
It's data about football data APIs, not match scores. No sign-up, no key. Facts as of ; check the vendor's page before relying on them.
Try it
Open any of these in a browser, or fetch them from your code. They're plain JSON files.
- Every endpoint, the MCP URL and the licence
- All 17 providers
- One provider (football-data.org)
- What changed, newest first
- The latest daily reachability check
Each provider also has its own file at /api/v1/providers/<slug>.json, where the slug is the last part of its page URL (e.g. /p/football-data-org/).
Add to your AI assistant
Our MCP server lets assistants like Claude, Cursor or ChatGPT look up providers, compare them and check what changed, with sources for every fact. The address is:
- https://footballapis.com/mcp
It's read-only and needs no login. Opening the address in a browser shows an error: it's meant for assistants, not people.
Claude Code (terminal)
claude mcp add --transport http footballapis https://footballapis.com/mcp
Claude desktop app or claude.ai: Settings → Connectors → Add custom connector, then paste the address above (where your plan supports custom connectors).
Cursor (~/.cursor/mcp.json)
{
"mcpServers": {
"footballapis": {
"url": "https://footballapis.com/mcp"
}
}
}
ChatGPT: where custom MCP connectors are supported (developer mode, depending on your plan), open Settings → Connectors (also called Apps), add a custom connector, paste the address above and choose no authentication.
Other tools (generic JSON config)
{
"mcpServers": {
"footballapis": {
"type": "http",
"url": "https://footballapis.com/mcp"
}
}
}
Menu names change often; if yours differ, look for "MCP", "connectors" or "tools" in your assistant's settings. Some tools call the transport "Streamable HTTP" or "HTTP".
What your assistant can do with it
list_providers
List providers, optionally only those with a free plan (or trial), under a monthly budget, covering a league or offering a data type.
get_provider
Everything we know about one provider: every price tier, free plan, leagues, data types, links and sources.
compare_providers
Two to five providers side by side.
recent_changes
What changed recently: price corrections, confirmed prices, changed source pages and site updates.
provider_health
Our daily check: was the provider’s public page (or keyless endpoint) reachable, and how fast. Not API uptime.
recommend_provider
Three picks for a need (free to start, live scores, big European leagues, betting odds, cheapest paid plan), by the same fixed rule as our home page.
Try asking:
- "Which football data APIs have a free plan and cover the Premier League?"
- "Compare football-data.org, Sportmonks and API-Football."
- "What is the cheapest paid plan for betting odds data?"
Every answer includes the sources and the date each group of facts was last checked, plus "Facts as of 2026-10-19. Verify on the vendor page." Recommendations use the same fixed rules as Pick by what you need; nobody pays for placement. Provider names are forgiving ("API-Football", "opta", "statsbomb"); if one is ambiguous, the answer lists the closest matches. A data type that costs extra reads "yes (paid add-on)", with the price when the vendor states it.
Licence
The data is free to use, including commercially, under CC BY 4.0. Please credit FootballAPIs.com with a link to footballapis.com, for example: "Data: FootballAPIs.com (CC BY 4.0)".
Prices, plans and coverage belong to each vendor and change without notice. We take care, but can't guarantee the data is complete or current.
Please be kind to it
- The data changes at most once a day, usually far less. Cache it — once a day is plenty.
- Keep to about one request per second, and don't hammer the server in loops.
- Need everything? Fetch providers.json once instead of every provider file.
There's no API key and no hard limit today. If abuse appears we may add rate limits.
Daily checks: how we check
Every day at 05:17 UTC we send one request to one public address per provider and record whether it answered and how fast. Provider pages show the latest result, e.g. "Checked today: public page reachable · 420 ms".
What we measure
- Reachable: the address answered with a success or redirect status (HTTP 2xx or 3xx) within 15 seconds. We don't follow redirects, so each check is exactly one request.
- Response time: milliseconds until the first response headers arrived, measured from Cloudflare's network (the location varies), so treat it as rough.
- The last 90 days: days checked, % reachable and the median response time, in checks.json and the MCP provider_health tool.
What we don't measure
- For 14 of 17 providers we check a public page (their status page if they have one, else their docs, else their homepage). A page that loads doesn't prove the API works, and we never call an API that needs a key.
- For 3 we call a keyless endpoint their docs allow without sign-up: OpenLigaDB, StatsBomb Open Data (Hudl), TheSportsDB. That is a real request, but one endpoint, once a day — not uptime.
- Not data freshness, accuracy, rate limits or the speed of paid plans.
For maintainers: each morning we also run node scripts/mcp-smoke.mjs, which calls every MCP tool against the live server and fails on any error.
Politeness
Our requests identify themselves as FootballAPIsBot/1.0 (+https://footballapis.com/about/). We read each site's robots.txt (at most once a week) and skip any address it disallows, showing "skipped (robots.txt)". We read at most the first 64 KB of each answer.
What we check for each provider
API-Football (API-Sports) · Public page (docs page)
https://www.api-football.com/documentation-v3
Data Sports Group (DSG) · Public page (homepage)
https://datasportsgroup.com/
Entity Sports · Public page (homepage)
https://www.entitysport.com/football-api/
football-data.org · Public page (docs page)
https://docs.football-data.org/
FootballAnt · Public page (homepage)
https://www.footballant.com/
Goalserve · Public page (docs page)
https://www.goalserve.com/en/sport-data-feeds/soccer-api/documentation
Highlightly · Public page (status page)
https://status.highlightly.net/
iSports API · Public page (docs page)
https://www.isportsapi.com/docs.html
OpenLigaDB · Keyless API endpoint (public keyless api endpoint)
https://api.openligadb.de/getavailablesports
SportDevs · Public page (homepage)
https://sportdevs.com/
Sportmonks · Public page (status page)
https://status.sportmonks.com/
Sportradar · Public page (docs page)
https://developer.sportradar.com/soccer/reference/soccer-api-overview
SportsDataIO (Soccer) · Public page (docs page)
https://sportsdata.io/developers/api-documentation/soccer
SportsGameOdds · Public page (docs page)
https://sportsgameodds.com/docs
Stats Perform (Opta) · Public page (homepage)
https://www.statsperform.com/opta/
StatsBomb Open Data (Hudl) · Open data file (open data file (competitions index))
https://raw.githubusercontent.com/statsbomb/open-data/master/data/competitions.json
TheSportsDB · Keyless API endpoint (keyless test endpoint (docs publish the free test key 123))
https://www.thesportsdb.com/api/v1/json/123/all_leagues.php
What's in a provider record
Field names are stable within /api/v1/; anything that breaks them gets a new version. Every file also carries apiVersion, generatedAt, dataAsOf, licence and disclaimer. "unknown" always means "not confirmed on public pages", never "no".
| Field | Type | Meaning |
|---|---|---|
| slug | string | Stable ID, the same as the page URL /p/<slug>/. |
| name | string | Provider name. |
| aliases | array | Other well-known names (e.g. "API-Sports", "Opta", "StatsBomb"). The MCP tools accept the slug, name or any alias. |
| url | string | The provider page on FootballAPIs. |
| website, docsUrl, statusPage | string | null | Vendor links; null when we couldn't find one. |
| apiStyle | string | null | e.g. "REST", "REST + WebSockets (add-on)". |
| freePlan | "yes" | "trial" | "no" | "unknown" | "trial" = a free trial only, not an ongoing free plan. |
| freePlanNote | string | null | The free plan as the vendor describes it. |
| cheapestPaidKind | "numeric" | "quote" | "free" | "unknown" | "quote" = contact sales; "free" = no paid plans. |
| cheapestPaid | object | null | {display, amount, currency, period}: the lowest clear public paid price, at face value. period is "month" or null. |
| leagueCount | string | null | The vendor's own league count, as written. |
| leagues | object | One key per league (premier_league, championship, laliga, serie_a, bundesliga, ligue_1, primeira_liga, mls, champions_league): "yes" | "no" | "unknown". |
| dataTypes | object | One key per data type (e.g. live_scores, odds, xg): {state: "yes" | "addon" | "no" | "unknown", note}. "addon" = listed, but sold as a paid add-on on top of a plan (price in addons). A note about the vendor's website (not its API) counts as "unknown". |
| addons | object | Data types sold as a paid add-on, with the price as written: e.g. {"odds": "€15/mo"}; null = price not stated on the page we hold. Empty when there are none. addonDetails adds {price, source, note} per add-on. |
| pricing | array | Every public plan: {plan, price, limits}, as written on the vendor page. |
| verification | object | Per fact group (pricing, free_tier, coverage, data_types): {status: "verified" | "partial" | "unverified", lastVerified, sources, note, confidence, confidenceLabel, independentSource, crossChecks}. |
| verification.*.confidence | "vendor_plus_independent" | "vendor_only" | "unconfirmed" | Two-source check: vendor_plus_independent = Confirmed by vendor + 1 independent source; vendor_only = Vendor page only; unconfirmed = ? not confirmed. The vendor's own page is required; independentSource is the confirming URL (else null). crossChecks lists every independent page we looked at: {url, party, kind, confirms, conflict, note}. Rule: /how-we-check/#confidence. |
| lastChecked | string | null | Most recent lastVerified date across fact groups. |
| sources | array | Every public page used. |
changes.json: {date, type, provider, summary, sources, url}, where type is price_correction, price_confirmed, source_changed or site and provider is a slug or null. checks.json: {generatedAt, schedule, label, userAgent, latest, last90}; each result is {slug, target, kind, checkedAt, status, ok, ms} plus error or skipped when relevant.
Older download links
The original files still work and are updated with every build: /data/providers.json (our raw data file, snake_case fields) and /data/providers.csv (one row per provider, for spreadsheets). For new projects use /api/v1/.