Data analysis on Football Stats
Explore how to access, query and analyze football data using the Highlightly Football API. From player stats to match insights, we will break down what data is available and how you can use it for your own projects.

Many people today share two passions: football and data science. Both hobbyists and professionals often combine these interests to create exciting data-driven projects such as building prediction models, creating dashboards or writing analysis blogs. However, one of the biggest challenges that developers and analysts face is finding reliable, real-time data without paying high fees for enterprise-level APIs.
In this guide, we will show you how to use the Highlightly Football API to access up-to-date information about players, matches and leagues without the heavy costs that normally come with enterprise level sports data providers. The API offers a wide range of endpoints covering everything from live scores to advanced stats, making it an ideal tool for personal and small to medium scale professional use.
Since many data analysts work in Python, this article will include code examples tailored to Python users. By the end, you will know how to retrieve key football data and begin analyzing it for your own use cases.
Getting started
Using Highlightly Football API is straightforward. To start using the API service you will first need to create an account via Highlightly or RapidAPI.
Ensure that your API key is never exposed to the public.
To retrieve the data from the API, use one of the below URLs, depending on where you created your account:
- https://soccer.highlightly.net — Highlightly API base url
- https://football-highlights-api.p.rapidapi.com — RapidAPI API base url
Each API request must have the following HTTP headers:
-
x-rapid-api
— Highlightly or RapidAPI API token -
x-rapidapi-host
— Only needed for usage through RapidAPI. For the Football API usefootball-highlights-api.p.rapidapi.com
For demo mode purposes, we will focus on retrieving and analyzing match-specific data.
Retrieving match statistics
To get started with your analysis, the first step is to retrieve the list of supported leagues and select the league IDs relevant to your project.
You can access the full list of leagues using the following endpoints:
-
RapidAPI:
https://football-highlights-api.p.rapidapi.com/leagues
-
Highlightly:
https://soccer.highlightly.net/leagues
You can narrow down and filter the results by applying various query
parameters such as
countryCode
,
countryName
,
season
, and others. Here’s a sample
code snippet to demonstrate how to do that:
import http.client
import json
conn = http.client.HTTPSConnection("football-highlights-api.p.rapidapi.com")
headers = {
'x-rapidapi-key': "API TOKEN",
'x-rapidapi-host': "football-highlights-api.p.rapidapi.com"
}
offset = 0
all_data = []
while True:
endpoint = f"/leagues?offset={offset}"
conn.request("GET", endpoint, headers=headers)
res = conn.getresponse()
data = res.read()
decoded = data.decode("utf-8")
try:
json_data = json.loads(decoded)
items = json_data.get("data", [])
except json.JSONDecodeError:
print("Failed to decode response.")
break
if not items:
break # The API has no more data
all_data.extend(items)
offset += 100
print(json.dumps(all_data, indent=2))
It is important to note that the data returned from this endpoint is
paginated, where only the first 100 records are included per request.
To retrieve the full dataset, you will need to make multiple requests,
incrementing the offset
query
parameter by 100 each time, until the API returns an empty
data
array.
To save you some time, here is a list of commonly analyzed football
leagues, along with their respective
leagueId
and
countryCode
values:
-
Premier League —
leagueId
: 33973,countryCode
: GB-ENG -
Championship —
leagueId
: 34824,countryCode
: GB-ENG -
La Liga —
leagueId
: 119924,countryCode
: ES -
Bundesliga —
leagueId
: 67162,countryCode
: DE -
Ligue 1 —
leagueId
: 52695,countryCode
: FR -
Serie A —
leagueId
: 115669,countryCode
: IT -
UEFA Champions League —
leagueId
: 2486,countryCode
: World -
UEFA Europa Conference League —
leagueId
: 722432,countryCode
: World -
UEFA Europa League —
leagueId
: 3337,countryCode
: World
With the relevant leagueIds
we can
now move on to fetching match data. Let’s refine our code a bit to
improve reusability and readability:
import http.client
import json
from urllib.parse import urlencode, urlunparse
API_TOKEN = "API TOKEN"
HOST = "football-highlights-api.p.rapidapi.com"
headers = {
'x-rapidapi-key': API_TOKEN,
'x-rapidapi-host': HOST
}
def fetch_paginated(path, params):
conn = http.client.HTTPSConnection(HOST)
offset = 0
all_results = []
while True:
params["offset"] = offset
query_string = urlencode(params)
url = f"{path}?{query_string}"
conn.request("GET", url, headers=headers)
res = conn.getresponse()
data = res.read()
decoded = json.loads(data.decode("utf-8"))
results = decoded.get("data", [])
if not results:
break # The API has no more data
all_results.extend(results)
offset += 100
return all_results
leagues = fetch_paginated("/leagues", { "limit": 100 })
matches = fetch_paginated("/matches", {
"timezone": "Europe/London",
"date": "2025-05-31",
"leagueId": 2486,
"limit": 100
})
print(json.dumps(leagues, indent=2))
print(json.dumps(matches, indent=2))
For demonstration purposes, we retrieved all UEFA Champions League
matches played on May 31st, 2025. As expected, only a single match
took place on that date. However, it’s important to note that the
/matches
endpoint is also paginated,
just like the /leagues
endpoint.
Below is a sample of the API response for that request:
{
"data": [
{
"id": 1169965796,
"round": "Final",
"date": "2025-05-31T19:00:00.000Z",
"country": {
"code": "World",
"name": "World",
"logo": "https://highlightly.net/soccer/images/countries/World.png"
},
"state": {
"clock": 90,
"score": {
"current": "5 - 0",
"penalties": null
},
"description": "Finished"
},
"awayTeam": {
"id": 430539,
"logo": "https://highlightly.net/soccer/images/teams/430539.png",
"name": "Inter"
},
"homeTeam": {
"id": 73119,
"logo": "https://highlightly.net/soccer/images/teams/73119.png",
"name": "Paris Saint Germain"
},
"league": {
"id": 2486,
"logo": "https://highlightly.net/soccer/images/leagues/2486.png",
"name": "UEFA Champions League",
"season": 2024
}
}
],
"plan": {
"tier": "BASIC",
"message": "All data available with current plan."
},
"pagination": {
"totalCount": 1,
"offset": 0,
"limit": 100
}
}
As we can see, the /matches
route
does not include any statistics data. To retrieve detailed match
stats, we will need to make another HTTP request to the
/matches/1169965796
route.
Let's extend our code by creating another function to retrieve match details:
def fetch_match_details(match_id):
conn = http.client.HTTPSConnection(HOST)
endpoint = f"/matches/{match_id}"
conn.request("GET", endpoint, headers=headers)
res = conn.getresponse()
data = res.read()
try:
decoded = json.loads(data.decode("utf-8"))
except json.JSONDecodeError:
print("Failed to decode match response")
return None
return decoded
To retrieve the match details, we simply have to call the above function with the correct match id:
match_details = fetch_match_details("1169965796")
print(json.dumps(match_details, indent=2))
The above call would result in the following data:
[
{
"venue": {
"city": "Munich",
"name": "Allianz Arena",
"country": "Germany",
"capacity": "75000"
},
"referee": {
"name": "Kovacs, Istvan",
"nationality": "Romania"
},
"forecast": {
"status": "cloudy",
"temperature": "23.38°C"
},
"events": [
{
"team": {
"id": 73119,
"logo": "https://highlightly.net/soccer/images/teams/73119.png",
"name": "Paris Saint Germain"
},
"time": "12",
"type": "Goal",
"assist": "D. Doue",
"player": "A. Hakimi",
"substituted": null
},
{
"team": {
"id": 73119,
"logo": "https://highlightly.net/soccer/images/teams/73119.png",
"name": "Paris Saint Germain"
},
"time": "20",
"type": "Goal",
"assist": "O. Dembele",
"player": "D. Doue",
"substituted": null
},
{
"team": {
"id": 430539,
"logo": "https://highlightly.net/soccer/images/teams/430539.png",
"name": "Inter"
},
"time": "53",
"type": "Substitution",
"assist": null,
"player": "Y. Bisseck",
"substituted": "B. Pavard"
},
{
"team": {
"id": 430539,
"logo": "https://highlightly.net/soccer/images/teams/430539.png",
"name": "Inter"
},
"time": "53",
"type": "Substitution",
"assist": null,
"player": "N. Zalewski",
"substituted": "F. Dimarco"
},
{
"team": {
"id": 430539,
"logo": "https://highlightly.net/soccer/images/teams/430539.png",
"name": "Inter"
},
"time": "56",
"type": "Yellow Card",
"assist": null,
"player": "N. Zalewski",
"substituted": null
},
{
"team": {
"id": 430539,
"logo": "https://highlightly.net/soccer/images/teams/430539.png",
"name": "Inter"
},
"time": "58",
"type": "Yellow Card",
"assist": null,
"player": "S. Inzaghi",
"substituted": null
},
{
"team": {
"id": 430539,
"logo": "https://highlightly.net/soccer/images/teams/430539.png",
"name": "Inter"
},
"time": "62",
"type": "Substitution",
"assist": null,
"player": "Carlos Augusto",
"substituted": "H. Mkhitaryan"
},
{
"team": {
"id": 430539,
"logo": "https://highlightly.net/soccer/images/teams/430539.png",
"name": "Inter"
},
"time": "62",
"type": "Substitution",
"assist": null,
"player": "M. Darmian",
"substituted": "Y. Bisseck"
},
{
"team": {
"id": 73119,
"logo": "https://highlightly.net/soccer/images/teams/73119.png",
"name": "Paris Saint Germain"
},
"time": "63",
"type": "Goal",
"assist": "Vitinha",
"player": "D. Doue",
"substituted": null
},
{
"team": {
"id": 73119,
"logo": "https://highlightly.net/soccer/images/teams/73119.png",
"name": "Paris Saint Germain"
},
"time": "65",
"type": "Yellow Card",
"assist": null,
"player": "D. Doue",
"substituted": null
},
{
"team": {
"id": 73119,
"logo": "https://highlightly.net/soccer/images/teams/73119.png",
"name": "Paris Saint Germain"
},
"time": "66",
"type": "Substitution",
"assist": null,
"player": "B. Barcola",
"substituted": "D. Doue"
},
{
"team": {
"id": 430539,
"logo": "https://highlightly.net/soccer/images/teams/430539.png",
"name": "Inter"
},
"time": "69",
"type": "Yellow Card",
"assist": null,
"player": "M. Thuram",
"substituted": null
},
{
"team": {
"id": 430539,
"logo": "https://highlightly.net/soccer/images/teams/430539.png",
"name": "Inter"
},
"time": "70",
"type": "Substitution",
"assist": null,
"player": "K. Asllani",
"substituted": "H. Calhanoglu"
},
{
"team": {
"id": 430539,
"logo": "https://highlightly.net/soccer/images/teams/430539.png",
"name": "Inter"
},
"time": "71",
"type": "Yellow Card",
"assist": null,
"player": "F. Acerbi",
"substituted": null
},
{
"team": {
"id": 73119,
"logo": "https://highlightly.net/soccer/images/teams/73119.png",
"name": "Paris Saint Germain"
},
"time": "73",
"type": "Goal",
"assist": "O. Dembele",
"player": "K. Kvaratskhelia",
"substituted": null
},
{
"team": {
"id": 73119,
"logo": "https://highlightly.net/soccer/images/teams/73119.png",
"name": "Paris Saint Germain"
},
"time": "78",
"type": "Substitution",
"assist": null,
"player": "L. Hernandez",
"substituted": "N. Mendes"
},
{
"team": {
"id": 73119,
"logo": "https://highlightly.net/soccer/images/teams/73119.png",
"name": "Paris Saint Germain"
},
"time": "84",
"type": "Substitution",
"assist": null,
"player": "G. Ramos",
"substituted": "K. Kvaratskhelia"
},
{
"team": {
"id": 73119,
"logo": "https://highlightly.net/soccer/images/teams/73119.png",
"name": "Paris Saint Germain"
},
"time": "84",
"type": "Substitution",
"assist": null,
"player": "S. Mayulu",
"substituted": "F. Ruiz"
},
{
"team": {
"id": 73119,
"logo": "https://highlightly.net/soccer/images/teams/73119.png",
"name": "Paris Saint Germain"
},
"time": "84",
"type": "Substitution",
"assist": null,
"player": "W. Zaire-Emery",
"substituted": "J. Neves"
},
{
"team": {
"id": 73119,
"logo": "https://highlightly.net/soccer/images/teams/73119.png",
"name": "Paris Saint Germain"
},
"time": "87",
"type": "Goal",
"assist": "B. Barcola",
"player": "S. Mayulu",
"substituted": null
},
{
"team": {
"id": 73119,
"logo": "https://highlightly.net/soccer/images/teams/73119.png",
"name": "Paris Saint Germain"
},
"time": "90+1",
"type": "Yellow Card",
"assist": null,
"player": "A. Hakimi",
"substituted": null
}
],
"predictions": {
"live": [
{
"type": "live",
"modelType": "three-way",
"description": "Paris Saint Germain is most likely to win the game against Inter.",
"generatedAt": "2025-05-31T19:00:12.842Z",
"probabilities": {
"away": "26.73%",
"draw": "27.14%",
"home": "46.13%"
}
},
{
"type": "live",
"modelType": "three-way",
"description": "Paris Saint Germain is most likely to win the game against Inter.",
"generatedAt": "2025-05-31T19:10:09.218Z",
"probabilities": {
"away": "25.94%",
"draw": "28.12%",
"home": "45.94%"
}
},
{
"type": "live",
"modelType": "three-way",
"description": "Paris Saint Germain is most likely to win the game against Inter.",
"generatedAt": "2025-05-31T19:20:13.454Z",
"probabilities": {
"away": "10.32%",
"draw": "20.38%",
"home": "69.29%"
}
},
{
"type": "live",
"modelType": "three-way",
"description": "Paris Saint Germain is most likely to win the game against Inter.",
"generatedAt": "2025-05-31T19:50:09.669Z",
"probabilities": {
"away": "3.13%",
"draw": "9.11%",
"home": "87.76%"
}
},
{
"type": "live",
"modelType": "three-way",
"description": "Paris Saint Germain is most likely to win the game against Inter.",
"generatedAt": "2025-05-31T20:00:13.524Z",
"probabilities": {
"away": "3.09%",
"draw": "9.08%",
"home": "87.82%"
}
},
{
"type": "live",
"modelType": "three-way",
"description": "Paris Saint Germain is most likely to win the game against Inter.",
"generatedAt": "2025-05-31T20:10:10.460Z",
"probabilities": {
"away": "3.13%",
"draw": "9.05%",
"home": "87.83%"
}
},
{
"type": "live",
"modelType": "three-way",
"description": "Paris Saint Germain is most likely to win the game against Inter.",
"generatedAt": "2025-05-31T20:20:24.309Z",
"probabilities": {
"away": "2.68%",
"draw": "8.59%",
"home": "88.73%"
}
},
{
"type": "live",
"modelType": "three-way",
"description": "Paris Saint Germain is most likely to win the game against Inter.",
"generatedAt": "2025-05-31T20:30:09.423Z",
"probabilities": {
"away": "1.11%",
"draw": "4.18%",
"home": "94.71%"
}
},
{
"type": "live",
"modelType": "three-way",
"description": "Paris Saint Germain is most likely to win the game against Inter.",
"generatedAt": "2025-05-31T20:40:11.117Z",
"probabilities": {
"away": "0.99%",
"draw": "3.62%",
"home": "95.39%"
}
}
],
"prematch": [
{
"type": "prematch",
"modelType": "three-way",
"description": "Paris Saint Germain is most likely to win the game against Inter.",
"generatedAt": "2025-05-24T03:11:58.294Z",
"probabilities": {
"away": "29.32%",
"draw": "28.62%",
"home": "42.06%"
}
},
{
"type": "prematch",
"modelType": "three-way",
"description": "Paris Saint Germain is most likely to win the game against Inter.",
"generatedAt": "2025-05-25T02:33:17.154Z",
"probabilities": {
"away": "29.26%",
"draw": "28.83%",
"home": "41.90%"
}
},
{
"type": "prematch",
"modelType": "three-way",
"description": "Paris Saint Germain is most likely to win the game against Inter.",
"generatedAt": "2025-05-26T01:53:53.702Z",
"probabilities": {
"away": "29.35%",
"draw": "28.82%",
"home": "41.83%"
}
},
{
"type": "prematch",
"modelType": "three-way",
"description": "Paris Saint Germain is most likely to win the game against Inter.",
"generatedAt": "2025-05-27T01:50:59.195Z",
"probabilities": {
"away": "30.32%",
"draw": "29.05%",
"home": "40.63%"
}
},
{
"type": "prematch",
"modelType": "three-way",
"description": "Paris Saint Germain is most likely to win the game against Inter.",
"generatedAt": "2025-05-28T01:51:35.186Z",
"probabilities": {
"away": "27.94%",
"draw": "28.54%",
"home": "43.52%"
}
},
{
"type": "prematch",
"modelType": "three-way",
"description": "Paris Saint Germain is most likely to win the game against Inter.",
"generatedAt": "2025-05-29T01:49:56.038Z",
"probabilities": {
"away": "28.14%",
"draw": "28.75%",
"home": "43.11%"
}
},
{
"type": "prematch",
"modelType": "three-way",
"description": "Paris Saint Germain is most likely to win the game against Inter.",
"generatedAt": "2025-05-30T01:39:57.879Z",
"probabilities": {
"away": "27.86%",
"draw": "28.86%",
"home": "43.28%"
}
},
{
"type": "prematch",
"modelType": "three-way",
"description": "Paris Saint Germain is most likely to win the game against Inter.",
"generatedAt": "2025-05-31T01:24:12.792Z",
"probabilities": {
"away": "28.27%",
"draw": "28.57%",
"home": "43.16%"
}
}
]
},
"id": 1169965796,
"round": "Final",
"date": "2025-05-31T19:00:00.000Z",
"country": {
"code": "World",
"name": "World",
"logo": "https://highlightly.net/soccer/images/countries/World.png"
},
"state": {
"clock": 90,
"score": {
"current": "5 - 0",
"penalties": null
},
"description": "Finished"
},
"awayTeam": {
"id": 430539,
"logo": "https://highlightly.net/soccer/images/teams/430539.png",
"name": "Inter",
"topPlayers": [
{
"name": "Lautaro Martínez",
"position": "Attacker",
"statistics": [
{
"name": "Shots On Target",
"value": 0
},
{
"name": "Minutes",
"value": 90
}
]
},
{
"name": "Kristjan Asllani",
"position": "Midfielder",
"statistics": [
{
"name": "Goals",
"value": 0
},
{
"name": "Assists",
"value": 0
},
{
"name": "Minutes",
"value": 21
}
]
},
{
"name": "Carlos Augusto",
"position": "Defender",
"statistics": [
{
"name": "Goals",
"value": 0
},
{
"name": "Assists",
"value": 0
},
{
"name": "Interceptions",
"value": 0
}
]
}
],
"shots": [
{
"time": "23'",
"outcome": "Missed",
"goalTarget": null,
"playerName": "Francesco Acerbi"
},
{
"time": "37'",
"outcome": "Missed",
"goalTarget": "CloseLeft",
"playerName": "Marcus Thuram"
},
{
"time": "55'",
"outcome": "Blocked",
"goalTarget": "Low Left",
"playerName": "Nicolo Barella"
},
{
"time": "56'",
"outcome": "Blocked",
"goalTarget": "Low Centre",
"playerName": "Nicola Zalewski"
},
{
"time": "59'",
"outcome": "Missed",
"goalTarget": null,
"playerName": "Nicolo Barella"
},
{
"time": "67'",
"outcome": "Blocked",
"goalTarget": "Low Centre",
"playerName": "Carlos Augusto"
},
{
"time": "75'",
"outcome": "Saved",
"goalTarget": "Low Centre",
"playerName": "Marcus Thuram"
},
{
"time": "81'",
"outcome": "Saved",
"goalTarget": "Low Centre",
"playerName": "Nicola Zalewski"
}
]
},
"homeTeam": {
"id": 73119,
"logo": "https://highlightly.net/soccer/images/teams/73119.png",
"name": "Paris Saint Germain",
"topPlayers": [
{
"name": "Désiré Doué",
"position": "Attacker",
"statistics": [
{
"name": "Shots On Target",
"value": 3
},
{
"name": "Minutes",
"value": 66
}
]
},
{
"name": "Vitinha",
"position": "Midfielder",
"statistics": [
{
"name": "Goals",
"value": 0
},
{
"name": "Assists",
"value": 1
},
{
"name": "Minutes",
"value": 90
}
]
},
{
"name": "Achraf Hakimi",
"position": "Defender",
"statistics": [
{
"name": "Goals",
"value": 1
},
{
"name": "Assists",
"value": 0
},
{
"name": "Interceptions",
"value": 0
}
]
}
],
"shots": [
{
"time": "7'",
"outcome": "Missed",
"goalTarget": null,
"playerName": "Marquinhos"
},
{
"time": "10'",
"outcome": "Saved",
"goalTarget": "Low Left",
"playerName": "Désiré Doué"
},
{
"time": "11'",
"outcome": "Saved",
"goalTarget": "Low Centre",
"playerName": "Ousmane Dembélé"
},
{
"time": "12'",
"outcome": "Goal",
"goalTarget": "Low Centre",
"playerName": "Achraf Hakimi"
},
{
"time": "18'",
"outcome": "Missed",
"goalTarget": null,
"playerName": "Khvicha Kvaratskhelia"
},
{
"time": "20'",
"outcome": "Goal",
"goalTarget": "High Right",
"playerName": "Désiré Doué"
},
{
"time": "27'",
"outcome": "Saved",
"goalTarget": "Low Centre",
"playerName": "Fabián Ruiz"
},
{
"time": "34'",
"outcome": "Blocked",
"goalTarget": "Low Left",
"playerName": "Ousmane Dembélé"
},
{
"time": "34'",
"outcome": "Missed",
"goalTarget": null,
"playerName": "Marquinhos"
},
{
"time": "44'",
"outcome": "Missed",
"goalTarget": null,
"playerName": "Ousmane Dembélé"
},
{
"time": "45 + 1'",
"outcome": "Missed",
"goalTarget": "Close Right",
"playerName": "Désiré Doué"
},
{
"time": "45 + 2'",
"outcome": "Blocked",
"goalTarget": "Low Left",
"playerName": "Khvicha Kvaratskhelia"
},
{
"time": "45 + 3'",
"outcome": "Missed",
"goalTarget": null,
"playerName": "Khvicha Kvaratskhelia"
},
{
"time": "46'",
"outcome": "Missed",
"goalTarget": "CloseLeft",
"playerName": "Khvicha Kvaratskhelia"
},
{
"time": "50'",
"outcome": "Missed",
"goalTarget": "Close Left And High",
"playerName": "Khvicha Kvaratskhelia"
},
{
"time": "52'",
"outcome": "Missed",
"goalTarget": "Close Right",
"playerName": "Ousmane Dembélé"
},
{
"time": "61'",
"outcome": "Blocked",
"goalTarget": "Low Centre",
"playerName": "Achraf Hakimi"
},
{
"time": "63'",
"outcome": "Goal",
"goalTarget": "Low Right",
"playerName": "Désiré Doué"
},
{
"time": "70'",
"outcome": "Missed",
"goalTarget": "Close High",
"playerName": "Bradley Barcola"
},
{
"time": "73'",
"outcome": "Goal",
"goalTarget": "Low Left",
"playerName": "Khvicha Kvaratskhelia"
},
{
"time": "81'",
"outcome": "Missed",
"goalTarget": "CloseLeft",
"playerName": "Bradley Barcola"
},
{
"time": "83'",
"outcome": "Missed",
"goalTarget": null,
"playerName": "Bradley Barcola"
},
{
"time": "86'",
"outcome": "Goal",
"goalTarget": "Low Left",
"playerName": "Senny Mayulu"
}
]
},
"league": {
"id": 2486,
"logo": "https://highlightly.net/soccer/images/leagues/2486.png",
"name": "UEFA Champions League",
"season": 2024
},
"statistics": [
{
"team": {
"id": 73119,
"logo": "https://highlightly.net/soccer/images/teams/73119.png",
"name": "Paris Saint Germain"
},
"statistics": [
{
"value": 0.35,
"displayName": "Shots accuracy"
},
{
"value": 8,
"displayName": "Shots on target"
},
{
"value": 12,
"displayName": "Shots off target"
},
{
"value": 3,
"displayName": "Blocked shots"
},
{
"value": 20,
"displayName": "Shots within penalty area"
},
{
"value": 3,
"displayName": "Shots outside penalty area"
},
{
"value": 13,
"displayName": "Fouls"
},
{
"value": 4,
"displayName": "Corners"
},
{
"value": 0,
"displayName": "Offsides"
},
{
"value": 0.59,
"displayName": "Possession"
},
{
"value": 2,
"displayName": "Yellow cards"
},
{
"value": 0,
"displayName": "Red cards"
},
{
"value": 2,
"displayName": "Goalkeeper saves"
},
{
"value": 529,
"displayName": "Total passes"
},
{
"value": 464,
"displayName": "Successful passes"
},
{
"value": 65,
"displayName": "Failed passes"
},
{
"displayName": "Expected Goals",
"value": 3.23
},
{
"displayName": "Big Chances Created",
"value": 8
},
{
"displayName": "Free Kicks",
"value": 6
},
{
"displayName": "Throw-Ins",
"value": 12
},
{
"displayName": "Goal Kicks",
"value": 5
}
]
},
{
"team": {
"id": 430539,
"logo": "https://highlightly.net/soccer/images/teams/430539.png",
"name": "Inter"
},
"statistics": [
{
"value": 0.25,
"displayName": "Shots accuracy"
},
{
"value": 2,
"displayName": "Shots on target"
},
{
"value": 3,
"displayName": "Shots off target"
},
{
"value": 3,
"displayName": "Blocked shots"
},
{
"value": 6,
"displayName": "Shots within penalty area"
},
{
"value": 2,
"displayName": "Shots outside penalty area"
},
{
"value": 7,
"displayName": "Fouls"
},
{
"value": 6,
"displayName": "Corners"
},
{
"value": 5,
"displayName": "Offsides"
},
{
"value": 0.41,
"displayName": "Possession"
},
{
"value": 3,
"displayName": "Yellow cards"
},
{
"value": 0,
"displayName": "Red cards"
},
{
"value": 3,
"displayName": "Goalkeeper saves"
},
{
"value": 352,
"displayName": "Total passes"
},
{
"value": 287,
"displayName": "Successful passes"
},
{
"value": 65,
"displayName": "Failed passes"
},
{
"displayName": "Expected Goals",
"value": 0.49
},
{
"displayName": "Big Chances Created",
"value": 1
},
{
"displayName": "Free Kicks",
"value": 12
},
{
"displayName": "Throw-Ins",
"value": 19
},
{
"displayName": "Goal Kicks",
"value": 12
}
]
}
],
"news": [
{
"datePublished": "2025-06-01T08:36:04Z",
"title": "Paris Saint-Germain will try to get Franco Mastantuono deal done as talks have been ongoing for weeks.",
"image": "https://pbs.twimg.com/media/GsVXf5qWYAEnjaf?format=jpg&name=900x900",
"url": "https://x.com/FabrizioRomano/status/1929093308761923599"
},
{
"datePublished": "2025-06-01T08:04:00Z",
"title": "Two dead and 192 injured as 426 arrests made in France chaos after PSG triumph",
"image": "https://i2-prod.mirror.co.uk/article35318413.ece/ALTERNATES/s1200/0_Paris-Saint-Germain-PSG-win-2025-UEFA-Champions-League-trophy-beating-Inter-Milan-5-0-in-final.jpg",
"url": "https://www.mirror.co.uk/sport/football/news/paris-france-chaos-psg-championsleague-35318406"
},
{
"datePublished": "2025-05-31T23:55:47Z",
"title": "New-look PSG make history on emotional night for Luis Enrique",
"image": "https://ichef.bbci.co.uk/ace/branded_sport/1200/cpsprodpb/c9d0/live/075e7f40-3e73-11f0-bace-e1270fc31f5e.jpg",
"url": "https://www.bbc.com/sport/football/articles/cnv1g944vggo"
},
{
"datePublished": "2025-05-31T23:33:00Z",
"title": "Luis Enrique 'emotional' after PSG unveil banner in tribute to late daughter",
"image": "https://e2.365dm.com/25/05/1920x1080/skysports-psg-champions-league_6932240.jpg?20250531225703",
"url": "https://www.skysports.com/football/news/11945/13377557/psg-win-champions-league-luis-enrique-emotional-after-supporters-unveil-banner-in-tribute-to-late-daughter"
},
{
"datePublished": "2025-05-31T23:27:50Z",
"title": "'Coming of age' - Doue announces himself to the world",
"image": "https://ichef.bbci.co.uk/ace/standard/1024/cpsprodpb/2f88/live/1728fab0-3e76-11f0-835b-310c7b938e84.jpg",
"url": "https://www.bbc.com/sport/football/videos/cgr5d8k8r2eo"
},
{
"datePublished": "2025-05-31T22:15:00Z",
"title": "Inter Milan boss Simone Inzaghi speaks to two Premier League clubs amid uncertain future",
"image": "https://talksport.com/wp-content/uploads/sites/5/2025/05/simone-inzaghi-head-coach-fc-999194232.jpg?strip=all&quality=100&w=1920&h=1080&crop=1",
"url": "https://talksport.com/football/3250350/inter-milan-simone-inzaghi-tottenham-hotspur-newcastle/"
},
{
"datePublished": "2025-05-31T21:51:39Z",
"title": "Donnarumma: 'Luis Enrique gave PSG calm, but Italy victory is different'",
"image": "https://icdn.football-italia.net/wp-content/uploads/2025/05/Gianluigi-Donnarumma-Inter-PSG-medal.jpg",
"url": "https://football-italia.net/donnarumma-luis-enrique-gave-psg-calm-italy/"
},
{
"datePublished": "2025-05-31T21:26:47Z",
"title": "New PSG star born as Champions League winners make history with record triumph",
"image": "https://i2-prod.mirror.co.uk/incoming/article35317910.ece/ALTERNATES/s1200/0_Paris-Saint-Germain-v-FC-Internazionale-Milano-UEFA-Champions-League-Final-2025.jpg",
"url": "https://www.mirror.co.uk/sport/football/match-reports/psg-inter-doue-goals-highlights-35317991"
},
{
"datePublished": "2025-05-31T21:02:36Z",
"title": "Mind and senses purified as PSG freed by Désiré Doué in gala performance to secure Champions League crown",
"image": "https://adrcezvpwp.cloudimg.io/v7/et-production-files.s3.amazonaws.com/media/extratime/images/articles/311a033b-b818-4df2-915b-048bdf0339fd.jpg?width=825&height=550",
"url": "https://www.extratime.com/fixtures/202425-uefa-champions-league-final/paris-saint-germain-v-inter/82926/4/report/"
},
{
"datePublished": "2025-05-31T21:00:00Z",
"title": "Rampant PSG thrash Inter to seal historic first Champions League title",
"image": "https://e1.365dm.com/25/05/1920x1080/skysports-psg-champions-league_6932212.jpg?20250531221256",
"url": "https://www.skysports.com/football/paris-saint-germain-vs-inter-milan/report/522734"
},
{
"datePublished": "2025-05-31T19:56:02Z",
"title": "PSG star Achraf Hakimi slammed for 'nonsense gimmick' in Champions League final",
"image": "https://i2-prod.mirror.co.uk/article35317681.ece/ALTERNATES/s1200/0_GettyImages-2217991827.jpg",
"url": "https://www.mirror.co.uk/sport/football/news/achraf-hakimi-psg-inter-milan-35317662"
},
{
"datePublished": "2025-05-31T19:53:01Z",
"title": "Victorious PSG eye 'cherry on the cake' at CWC",
"image": "https://a.espncdn.com/combiner/i?img=%2Fphoto%2F2025%2F0531%2Fr1500894_1296x729_16%2D9.jpg",
"url": "https://www.espn.com/soccer/story/_/id/45410743/champions-league-final-psg-continue-conquer-1st-title"
},
{
"datePublished": "2025-05-31T16:44:00Z",
"title": "Inter Milan ultras ambush PSG fans on Munich underground ahead of Champions League final",
"image": "https://cdn.images.express.co.uk/img/dynamic/67/1200x630/6199190.jpg",
"url": "https://www.express.co.uk/sport/football/2062612/inter-milan-psg-champions-league-final"
},
{
"datePublished": "2025-05-31T13:52:00Z",
"title": "Dimarco crowned 'one of the best in the world' by Roberto Carlos",
"image": "https://icdn.football-italia.net/wp-content/uploads/2024/12/Federico-Dimarco-Inter-celebrate.jpg",
"url": "https://football-italia.net/dimarco-crowned-one-of-the-best-in-the-world/"
},
{
"datePublished": "2025-05-31T08:24:45Z",
"title": "'Everybody was surprised' – How PSG moved on from Kylian Mbappe to become UCL finalists",
"image": "https://i2-prod.mirror.co.uk/article35315590.ece/ALTERNATES/s1200/1_Paris-Saint-Germain-v-Real-Sociedad-UEFA-Champions-League.jpg",
"url": "https://www.mirror.co.uk/sport/football/news/psg-champions-league-inter-mbappe-35315566"
},
{
"datePublished": "2025-05-31T06:30:00Z",
"title": "Champions League final: Clear favourites emerge in PSG vs Inter Milan predictions",
"image": "https://i2-prod.mirror.co.uk/article35314275.ece/ALTERNATES/s1200/1_Untitled-1.jpg",
"url": "https://www.mirror.co.uk/sport/football/news/champions-league-final-psg-inter-35312800"
},
{
"datePublished": "2025-05-30T22:41:20Z",
"title": "Champions League Final Preview: Paris Saint-Germain -v- Internazionale",
"image": "https://adrcezvpwp.cloudimg.io/v7/et-production-files.s3.amazonaws.com/media/extratime/images/articles/ee70645a-1315-4114-ae1b-a37f1ea2c3bb.png?width=825&height=550",
"url": "https://www.extratime.com/fixtures/202425-uefa-champions-league-final/paris-saint-germain-v-inter/82926/1/preview/"
},
{
"datePublished": "2025-05-30T19:42:41Z",
"title": "PSG vs Inter Milan: Preview and Prediction",
"image": "https://thehardtackle.com/wp-content/uploads/2015/08/04881521.jpg",
"url": "https://thehardtackle.com/round-up/2025/05/31/psg-vs-inter-milan-preview-and-prediction/"
},
{
"datePublished": "2025-05-30T19:11:32Z",
"title": "'A footballing architect' - how Enrique led PSG to brink of glory",
"image": "https://ichef.bbci.co.uk/ace/branded_sport/1200/cpsprodpb/7d8e/live/a3c5d2b0-3d89-11f0-8fa6-57e840e6fcdb.jpg",
"url": "https://www.bbc.com/sport/football/articles/c3e5d9gyx04o"
},
{
"datePublished": "2025-05-30T18:15:58Z",
"title": "Luis Enrique: 'Inter different to most teams, Donnarumma at highest level'",
"image": "https://icdn.football-italia.net/wp-content/uploads/2025/05/Luis-Enrique-PSG-press-conference.jpg",
"url": "https://football-italia.net/luis-enrique-inter-different-team-donnarumma/"
}
]
}
]
Explaining the statistics
Now that we have retrieved the data let's analyze and see what is available.
The most important field for custom analysis would be the
statistics
field. At the time of writing this blog, Highlightly classifies the
statistics into two categories:
-
baseline statistics which represent the base statistics which the
majority of matches will have:
- shot accuracy
- shots on target
- shots off target
- blocked shots
- shots within the penalty area
- shots outside the penalty area
- fouls
- corners
- offsides
- possession
- yellow cards
- red cards
- goalkeeper saves
- total passes
- successful passes
- failed passes
-
enhanced statistics which represent more advanced information which
might not be always available (less popular leagues won't have this
data available)
- big chances created
- free kicks
- crosses
- throw-ins
- goal kicks
- tackles
- expected goals (xG)
-
player goal shots
- time
- player name
- goal target (e.g. low centre)
- outcome (e.g. blocked)
- top players for each position and the associated statistics for their position (shots on target, goals, assists and interceptions)
You can also use the predictions
data
to further enhance your analytics dashboards or to feed them to your
machine learning/statistics models.
Now that we have seen what kind of data is available, let's take a look at some example ideas on what kind of analysis to perform:
-
basic match and team performance analysis
- compare team dominance (possession vs. successful passes)
- identify play styles (e.g. high possession vs. direct attack)
- disciplinary analysis (card frequency per team/referee/location)
-
shooting and finishing analysis
- shot heatmaps (where goals/shots occur most)
- finishing efficiency (shots on target vs. total shots)
- goal conversion rate by area (e.g. % scored from low centre)
- player accuracy and shot tendencies
-
passing and build-up play
- team passing efficiency
- build-up style comparison (short vs. long ball play)
- key pass contributors (can tie with big chances created)
-
defensive metrics
- defensive strength (tackles/saves per match)
- GK performance analysis (save percentage)
- high line tactics (offsides forced)
-
machine Learning / predictive models
- match outcome prediction
- player performance forecasting
- injury likelihood (based on minutes + tackles, etc.)
- fantasy point projections
-
various visualizations
- shot location charts
- passing accuracy bar plots
- xG vs actual goals scatterplots
- possession pie charts
Wrap up
There is a lot of data available, and with the right approach, many valuable insights can be uncovered. In this article, we introduced you to the basics of working with the Highlightly Football API, showing how to retrieve and analyze core match statistics.
However, this is just the beginning and Highlightly has much more to offer, including head-to-head comparisons, recent form (last five matches), detailed team stats, standings, match events and more.
Be sure to explore our documentation for a deeper look at the available data structures, advanced endpoints, and practical usage examples to use in your next football project.