How to Get Football Match Data with a REST API
Step-by-step tutorial: how to fetch football match data using a REST API. Includes working code examples in Python and JavaScript. Start for free with TheStatsAPI.
If you are building a football app, a stats dashboard, or a prediction model, the first thing you need is reliable match data. Scores, fixtures, dates, teams, competitions - all of it, delivered in a structured format your code can actually use.
This tutorial walks you through how to get football match data from a REST API, step by step. We will use TheStatsAPI as our data source because it covers 1,196 competitions and 84,000+ players with a clean REST JSON interface, and you can start with a 7-day free trial. By the end of this guide, you will have working code in both Python and JavaScript that fetches real match data and handles common edge cases.
Prerequisites
Before we start, make sure you have:
- Python 3.8+ or Node.js 18+ installed (we will show both)
- A code editor (VS Code, PyCharm, or anything you prefer)
- Basic familiarity with HTTP requests and JSON
- A TheStatsAPI account (we will set this up in the next section)
No frameworks or complex dependencies are required. We are working directly with HTTP requests to keep things simple and transferable to any stack.
Getting Your API Key
Every request to TheStatsAPI requires a Bearer token in the Authorization header. Here is how to get one:
- Go to thestatsapi.com and click Start Free Trial.
- Create your account. The 7-day trial gives you full access to every endpoint and all 1,196 competitions.
- Once logged in, navigate to the Dashboard. Your API key is displayed on the main dashboard page.
- Copy the key and store it somewhere safe. You will use it in every API call.
Your API key looks like a long alphanumeric string. Treat it like a password - do not commit it to public repositories or share it in client-side code.
Your First API Call in Python
Let's fetch today's football matches. Install the requests library if you do not already have it:
pip install requests
Now create a file called matches.py:
import requests
API_KEY = "your_api_key_here"
BASE_URL = "https://api.thestatsapi.com/api"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Accept": "application/json"
}
response = requests.get(f"{BASE_URL}/football/matches", headers=headers)
if response.status_code == 200:
data = response.json()
matches = data.get("data", [])
print(f"Found {len(matches)} matches\n")
for match in matches[:10]:
home = match["home_team"]["name"]
away = match["away_team"]["name"]
score_home = match.get("home_score", "-")
score_away = match.get("away_score", "-")
status = match.get("status", "unknown")
print(f"{home} {score_home} - {score_away} {away} [{status}]")
else:
print(f"Error: {response.status_code}")
print(response.text)
Run it:
python matches.py
You should see a list of matches with team names, scores, and match status. The response includes match metadata like the competition name, round, venue, and timestamps - everything you need to build a fixture list or results page.
Understanding the Response
Each match object in the data array includes fields like:
id- unique match identifierhome_teamandaway_team- team objects withid,name, and other detailshome_scoreandaway_score- final or current scoresstatus- match status (e.g.,finished,scheduled,postponed)date- match date and time in ISO 8601 formatcompetition- the league or cup this match belongs toseason- the season context
Fetching Matches by Competition
In most real applications, you do not want every match from every league. You want matches from a specific competition. Use the competition_id query parameter to filter:
import requests
API_KEY = "your_api_key_here"
BASE_URL = "https://api.thestatsapi.com/api"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Accept": "application/json"
}
# Fetch Premier League matches
params = {
"competition_id": 1, # Replace with the actual competition ID
}
response = requests.get(
f"{BASE_URL}/football/matches",
headers=headers,
params=params
)
data = response.json()
matches = data.get("data", [])
print(f"Found {len(matches)} matches in this competition\n")
for match in matches[:5]:
date = match["date"][:10]
home = match["home_team"]["name"]
away = match["away_team"]["name"]
score_home = match.get("home_score", "-")
score_away = match.get("away_score", "-")
print(f"[{date}] {home} {score_home} - {score_away} {away}")
Handling Pagination
When a competition has hundreds of matches, the API paginates results. The response includes pagination metadata:
data = response.json()
current_page = data["meta"]["current_page"]
last_page = data["meta"]["last_page"]
total = data["meta"]["total"]
print(f"Page {current_page} of {last_page} ({total} total matches)")
To fetch all pages, loop through them:
all_matches = []
page = 1
while True:
params = {"competition_id": 1, "page": page}
response = requests.get(
f"{BASE_URL}/football/matches",
headers=headers,
params=params
)
data = response.json()
all_matches.extend(data["data"])
if page >= data["meta"]["last_page"]:
break
page += 1
print(f"Fetched {len(all_matches)} total matches")
JavaScript Version with fetch()
Here is the same workflow in JavaScript using the built-in fetch API (Node.js 18+ or any modern browser):
const API_KEY = "your_api_key_here";
const BASE_URL = "https://api.thestatsapi.com/api";
async function getMatches(competitionId) {
const url = new URL(`${BASE_URL}/football/matches`);
if (competitionId) {
url.searchParams.set("competition_id", competitionId);
}
const response = await fetch(url, {
headers: {
Authorization: `Bearer ${API_KEY}`,
Accept: "application/json",
},
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
return data;
}
async function main() {
try {
const result = await getMatches();
const matches = result.data;
console.log(`Found ${matches.length} matches\n`);
matches.slice(0, 10).forEach((match) => {
const home = match.home_team.name;
const away = match.away_team.name;
const scoreHome = match.home_score ?? "-";
const scoreAway = match.away_score ?? "-";
console.log(`${home} ${scoreHome} - ${scoreAway} ${away}`);
});
} catch (error) {
console.error("Failed to fetch matches:", error.message);
}
}
main();
To paginate in JavaScript:
async function getAllMatches(competitionId) {
let allMatches = [];
let page = 1;
let lastPage = 1;
do {
const url = new URL(`${BASE_URL}/football/matches`);
url.searchParams.set("competition_id", competitionId);
url.searchParams.set("page", page);
const response = await fetch(url, {
headers: {
Authorization: `Bearer ${API_KEY}`,
Accept: "application/json",
},
});
const data = await response.json();
allMatches = allMatches.concat(data.data);
lastPage = data.meta.last_page;
page++;
} while (page <= lastPage);
return allMatches;
}
Common Errors and How to Fix Them
When working with any REST API, you will encounter HTTP errors. Here are the three most common ones and how to handle them.
401 Unauthorized
Your API key is missing, invalid, or expired.
HTTP 401: Unauthorized
Fix: Double-check your API key. Make sure the Authorization header uses the format Bearer your_api_key_here - with the word "Bearer" followed by a space. If your trial has expired, you will need to subscribe to a plan.
429 Too Many Requests
You have exceeded the rate limit for your plan.
HTTP 429: Too Many Requests
Fix: TheStatsAPI rate limits are 30 requests per minute on the Starter plan, 60/min on Growth, and 300/min on Scale. Add a delay between requests when fetching in bulk:
import time
for page in range(1, total_pages + 1):
response = requests.get(url, headers=headers, params={"page": page})
if response.status_code == 429:
print("Rate limited. Waiting 60 seconds...")
time.sleep(60)
response = requests.get(url, headers=headers, params={"page": page})
# process response...
time.sleep(2) # 2-second delay between requests
404 Not Found
The endpoint or resource ID does not exist.
HTTP 404: Not Found
Fix: Verify the URL path and any IDs you are passing. A competition_id of 99999 will return a 404 if that competition does not exist. Use the competitions endpoint first to get valid IDs.
Next Steps
You now know how to fetch football match data from a REST API, filter by competition, handle pagination, and deal with common errors. Here are some directions to take this further:
- Add player statistics. Use the
/football/players/{id}/statsendpoint to pull goals, assists, and appearances for any player. See our player stats tutorial for a complete walkthrough. - Build a dashboard. Combine match data with a frontend framework like Next.js to create a live stats dashboard. Our Next.js tutorial covers this end to end.
- Fetch historical data. TheStatsAPI includes 20+ years of match history - perfect for building prediction models or analyzing trends. Check the historical data guide.
- Explore all 1,196 competitions. Start with the
/football/competitionsendpoint to browse all available leagues and cups, then filter matches by any competition you need.
TheStatsAPI offers a 7-day free trial on all plans, giving full access to all 1,196 competitions and 84,000+ players - making it the best way to evaluate a premium football API before committing. Sign up at thestatsapi.com and start building.
Ready to Power Your Sports App?
Start your 7-day free trial. All endpoints included on every plan.