GuidesSPORTS APIS

Free football API for JavaScript

For a JavaScript project, 5 free football APIs work straight from fetch() with no private key: OpenLigaDB, the openfootball JSON files, TheSportsDB with its public key 123, Sportscore and ESPN's soccer scoreboard. Of 9 football APIs we tested on 28 October 2026, football-data.org answers its X-Auth-Token preflight with Access-Control-Allow-Origin: http://localhost, so the browser blocks the token on every other origin, and the Fantasy Premier League API sends no CORS header at all. The free cors.dev proxy (no signup, GET and HEAD only, about 600 requests a minute per IP) fixes FPL and football-data.org's token-free lists; the token itself needs cors.dev Pro, $5 a month for 500,000 requests with a 7-day trial of 1,000 requests and no card.

Which free football API to use

Pick OpenLigaDB for current tables, openfootball for fixtures and past seasons, and football-data.org or API-Football for deeper data when a server can hold the key. Each endpoint was called on 28 October 2026 with a browser Origin header and again through https://proxy.cors.dev/.

Free football APIs tested from the browser, checked October 2026
APIFree tierKeyCORS from the browserThrough cors.dev
OpenLigaDBFree community API, Bundesliga and moreNoneYes, any originWorks, not needed
openfootballPublic domain JSON, 8 leagues for 2026-27NoneYes, any originWorks, not needed
TheSportsDB30 requests per minute, trimmed resultsPublic key 123 in the pathYes, any origin429, call it directly
SportscoreAbout 10,000 requests per day per IPNone, attribution linkYes, any originWorks, not needed
ESPN scoreboardUnofficial, no published limitNoneYes, any origin403, call it directly
Fantasy Premier LeagueUnofficial, Premier League onlyNoneNo CORS headersFree tier works
football-data.org12 competitions, 10 calls per minuteX-Auth-Token headerNo, preflight allows http://localhost onlyLists free, token needs cors.dev Pro
API-Football100 requests per day, 10 per minutex-apisports-key headerYes, when the key is sentNot needed, free tier refuses the key
Sportmonks2 leagues, 3,000 calls per entity per hourapi_token or AuthorizationNo CORS headersWorks with api_token in the URL

Football data with no key and no proxy

OpenLigaDB (api.openligadb.de) is a free community project: reading needs no key or account, and it sends Access-Control-Allow-Origin: *. /getbltable/bl1/2026 returned the 18-team Bundesliga 2026/27 table (4,382 bytes), and /getavailableleagues lists all 840 leagues with shortcuts such as bl1, bl2, la1 and pl.

Bundesliga table from OpenLigaDB, no key, no proxy
// OpenLigaDB sends Access-Control-Allow-Origin: *, so call it directly with no key
const league = 'bl1'; // bl2, bl3 and other shortcuts come from /getavailableleagues
const season = 2026; // the year the season starts

const response = await fetch(`https://api.openligadb.de/getbltable/${league}/${season}`);
if (!response.ok) throw new Error(`OpenLigaDB answered ${response.status}`);

const table = await response.json();
table.forEach((team, index) => {
  console.log(`${index + 1}. ${team.teamName} ${team.points} pts (${team.goals}:${team.opponentGoals})`);
});

Community leagues are only as current as their editors: on 28 October 2026 LaLiga (la1) had results to 25 October, the Premier League (pl) only to 12 October.

openfootball publishes public domain (CC0) JSON on GitHub. The 2026-27 folder holds 8 leagues (en.1, en.2, de.1, es.1, it.1, fr.1, nl.1, pt.1), served with Access-Control-Allow-Origin: * from both raw.githubusercontent.com and cdn.jsdelivr.net. en.1.json lists all 380 Premier League fixtures in 55,359 bytes, but only 45 had a full-time score, the latest from 20 September 2026.

Three more need no private key and send Access-Control-Allow-Origin: *; call each one directly:

  • TheSportsDB: the public key 123 goes in the path, as in /api/v1/json/123/searchteams.php?t=Arsenal, and free results stop at 1 team per search, 5 table rows and 1 next match. Through cors.dev it answered a Cloudflare 429.
  • Sportscore: sportscore.com/api/widget/matches/?sport=football&limit=10 returned 10 matches with no key. Pages that use the data must show a visible dofollow "Powered by SportScore" link.
  • ESPN: the unofficial scoreboard at site.api.espn.com/apis/site/v2/sports/soccer/eng.1/scoreboard returned 102,731 bytes; call it directly, since ESPN answers 403 through cors.dev. The ESPN API guide covers its other endpoints.

football-data.org and its localhost-only preflight

football-data.org's free plan covers 12 competitions (PL, ELC, BL1, SA, PD, FL1, DED, PPL, BSA, CL, EC, WC) with fixtures, tables and delayed scores at 10 calls per minute, using a free token in the X-Auth-Token header. Without a token you get 100 requests per 24 hours for the area and competition lists only; /v4/competitions/PL/standings returned 403 "The resource you are looking for is restricted".

The token header triggers a preflight, which football-data.org answered with Access-Control-Allow-Origin: http://localhost for every origin we sent, including http://localhost:5173. Only a page on exactly http://localhost, port 80, matches, so dev servers on other ports and every deployed site get a CORS error with a valid token. The token-free /v4/competitions (190 competitions, 73,822 bytes) has no CORS header either, but returns 200 with one through the free cors.dev proxy.

The token cannot ride on the free tier: a request carrying X-Auth-Token answered 400 with X-Cors-Error: header_not_allowed. cors.dev Pro forwards it for $5 a month and 500,000 requests, with a 7-day trial of 1,000 requests and no card:

  1. Sign up

    Create an account at cors.dev/signup with Google.

  2. Create a Connection

    Add your exact page origin and the target host api.football-data.org.

  3. Send both headers

    Put the Connection's publishable key in X-Cors-Key and your token in X-Auth-Token.

football-data.org standings through cors.dev Pro
const PROXY = 'https://proxy.cors.dev/';
const target = 'https://api.football-data.org/v4/competitions/PL/standings';

const response = await fetch(PROXY + target, {
  headers: {
    'X-Cors-Key': 'YOUR_CONNECTION_KEY', // publishable, works only from your registered origins
    'X-Auth-Token': 'YOUR_FOOTBALL_DATA_TOKEN', // visible in DevTools: internal tools and prototypes only
  },
});
const proxyError = response.headers.get('X-Cors-Error');
if (proxyError) throw new Error(`cors.dev: ${proxyError}`);
if (!response.ok) throw new Error(`football-data.org answered ${response.status}`);

const { standings } = await response.json();
const total = standings.find((standing) => standing.type === 'TOTAL');
for (const row of total.table) {
  console.log(`${row.position}. ${row.team.shortName} ${row.points} pts, ${row.playedGames} played`);
}

The token stays visible in DevTools, and football-data.org's 10 calls per minute still apply. cors.dev Pro fits internal tools, prototypes and apps where each user pastes their own token; a public site running on your token should call football-data.org from a backend.

API-Football keys in the browser

API-Football (v3.football.api-sports.io) takes the key in the x-apisports-key header and works from fetch() directly, no proxy needed. Its preflight answered 204 with Access-Control-Allow-Origin: * and allowed x-apisports-key, x-rapidapi-key and authorization, and a GET with a key header came back with the same wildcard.

Without any key, /status returned 403 with no CORS header, so a missing key shows up as a CORS error; an invalid key returns 200 with an errors.token message. Any visitor can copy the key from DevTools and spend your 100 daily requests, so keep a production key behind a server route. The free cors.dev proxy refuses x-apisports-key with 400 header_not_allowed.

Sportmonks and the Fantasy Premier League API

Sportmonks' free plan covers the Danish Superliga and the Scottish Premiership with 3,000 API calls per entity per hour, no card and no expiry. It sent no CORS headers on its 401 response or on preflight, so fetch() fails, and its FAQ says to keep the token on your server.

The token goes in the api_token query parameter or the Authorization header. The free cors.dev tier refuses Authorization but forwards query strings as-is: a test api_token got Sportmonks' own 401 Invalid token provided back, with CORS headers added. A token in a URL is readable in DevTools, so keep this to prototypes.

The Fantasy Premier League API needs no key but sends no Access-Control-Allow-Origin header. Through the free proxy, fantasy.premierleague.com/api/bootstrap-static/ returned 200 with 1,788,526 bytes, inside the 6 MiB free response limit.

Free limits to plan for

  • football-data.org: 10 calls per minute; "Free w/ Livescores" is EUR 12 a month for live scores and 20 calls per minute.
  • API-Football: 100 requests per day, 10 per minute and limited seasons. API-Football's Pro plan is $19 a month for 7,500 per day, prepaid with no auto-renewal.
  • Sportmonks: 3,000 calls per entity per hour on 2 leagues; Starter is EUR 29 a month for 5 leagues, with a 14-day trial.
  • cors.dev: free needs no signup and allows GET and HEAD at about 600 requests a minute per IP, with 6 MiB responses. cors.dev Pro is $5 a month for 500,000 requests at 3,000 requests a minute per account and 100 in flight, and forwards custom headers such as X-Auth-Token.

Good questions.

Is there a free football API that needs no API key?

Yes. OpenLigaDB, the openfootball JSON files, Sportscore and ESPN's unofficial soccer scoreboard need no key, and TheSportsDB works with its public key 123. All five send Access-Control-Allow-Origin: *, so fetch() works from the browser with no proxy.

Why does football-data.org give a CORS error on localhost?

Its preflight for X-Auth-Token answers Access-Control-Allow-Origin: http://localhost, with no port, whatever origin you send. A dev server on http://localhost:5173 or http://localhost:3000 does not match, so the browser blocks the request even with a valid token. Call it from a server, or through cors.dev Pro, which forwards X-Auth-Token.

Is API-Football free?

Yes: 100 requests per day and 10 per minute, with limited seasons; API-Football's Pro plan costs $19 a month for 7,500 per day. It sends Access-Control-Allow-Origin: * when the x-apisports-key header is present, so it works from the browser, but every visitor can see the key.

Why did the free cors.dev proxy answer 400 header_not_allowed?

The free tier forwards only Accept, Accept-Language, If-None-Match, If-Modified-Since and Range, and answers 400 header_not_allowed to credential headers such as X-Auth-Token, x-apisports-key, X-API-Key and Authorization. A cors.dev Pro Connection key in X-Cors-Key lets them through.

Does cors.dev hide my football API key?

No. A key in browser code, in a header like X-Auth-Token or a URL parameter like api_token, is visible in the DevTools network tab. cors.dev Pro suits internal tools, prototypes and apps where each user brings their own token; a public site running on your key needs a backend.