Live now!

Progress of current post

How to Build soccer player data profiles using Sportmonks Football API

Are you a sports data analyst or app developer trying to build a soccer player data profile but worried over the number of APIs you have to integrate for a smashing player profile?

Time to read 7 min
Published 24 February 2025
Last updated 14 March 2025
Wesley Van Rooij
How to Build soccer player data profiles using Sportmonks Football API
Contents

Look no further, as Sportmonks Football API not only provides every endpoint you could ever dream of for player profiles but also every tool you could use to access it.

It doesn’t matter if you are a basic user or a data rockstar looking to create a comprehensive player profile, join us in this episode of our guide as we go over six steps on how to build soccer player data profiles.

Why are Soccer player data profiles important?

The importance of soccer player data cannot be overemphasised, as it serves as a crucial tool in modern football, providing valuable insights across various aspects of the game. Hence, it allows data-reliant stakeholders such as coaches and analysts to track detailed performance metrics, such as passing accuracy, dribbling success, and defensive contributions.

By understanding these statistics, team analysts can identify strengths and weaknesses in players, helping them tailor training programs for improvement where necessary.

For clubs and scouts, player data profiles are essential in the recruitment process. Rather than focusing on only one specific metric, such as goals, they can rely on a wide range of indicators to make decisions and player evaluations.

Fantasy football platforms and sports betting markets also rely on player data. Fantasy football players use these profiles to make informed selections, while bookmakers and bettors analyse trends, injury histories, and player form to make calculated decisions.

How about commentaries? Commentators rely on player statistics for pre-match, post-match and in-play analysis to drive deep fan engagement.

In addition, artificial intelligence and predictive analytics have taken player data analysis a few notches up. Many clubs apply machine learning models to predict a player’s potential impact on the squad based on his data profile.

We will show you a practical example of how to build a player’s soccer data profile using Sportmonks Football API and a programming language of choice.

Let’s get started!

STEP 1 – Gather the required tools

1. A free account from Sportmonks

Sign up for a free trial on mySportmonks.com, which also comes along with lifetime free access to the Scottish Premier League and Danish Superliga.

2. An API Token

After creating your account, head over to the ‘API Token’ section on your dashboard and provide a name for your token. Copy and save your new API token, which is required for authentication in a safe place. You may also delete and create a new API Token if it becomes compromised.

Creat-API-Token_Sportmonks

 

Step 2 – Choose a Programming Language & IDE

What programming language do you use? It doesn’t matter as data from Sportmonks Football API can be accessed by a wide number of programming languages. For today’s exercise, we shall use Scala, a strong, statically typed, high-level, general-purpose programming language that supports both object-oriented programming and functional programming.

A code editor such as Visual Studio Code or IntelliJ IDEA is required to compile and run our Scala code. Choosing the latter, you can download the community edition of IntelliJ IDEA.

After downloading, install a plug-in for Scala via the marketplace. You may refer to the official guide for Scala on IntelliJ IDEA.

Assuming all has gone according to plan, we can move on to step 3.

Scala-IntelliJ-Plugin

STEP 3: Choose a player of Interest

You are spoilt for choices on player selection. However, for today’s exercise, we shall settle for Virgil van Dijk, who is Liverpool’s captain, a well-known figure in the Reds’ backline.
Head over to the ID finder https://my.sportmonks.com/resources/id-finder/players on your dashboard to retrieve his assigned player ID (1743).

Using the URL https://api.sportmonks.com/v3/football/players/1743?api_token=API_Token, we can take a look at our selected player of interest, retrieving details such as name and age based on his date of birth and other personal details such as height, position, and nationality, along with a headshot.

import scala.io.Source
import java.net.URL
import java.nio.charset.CodingErrorAction
import scala.io.Codec
import scala.util.matching.Regex
import java.time.{LocalDate, Period}
import java.time.format.DateTimeFormatter

object SportMonksExample extends App {
 
  val apiToken = "API Token"  // Replace this with your actual API token.
  val playerId = "1743"
  val url = s"https://api.sportmonks.com/v3/football/players/$playerId?api_token=$apiToken"

  // Handle potential character decoding issues.
  implicit val codec: Codec = Codec("UTF-8")
  codec.onMalformedInput(CodingErrorAction.REPLACE)
  codec.onUnmappableCharacter(CodingErrorAction.REPLACE)

  try {
    // Open a connection to the URL and read the response.
    val response = Source.fromURL(new URL(url)).mkString

    // Define regex patterns to extract the required fields.
    val displayNamePattern: Regex = """"display_name"\s*:\s*"([^"]+)"""".r
    val nationalityPattern: Regex = """"nationality_id"\s*:\s*(\d+)""".r
    val positionPattern: Regex = """"position_id"\s*:\s*(\d+)""".r
    val headshotPattern: Regex = """"image_path"\s*:\s*"([^"]+)"""".r
    val dobPattern: Regex = """"date_of_birth"\s*:\s*"([^"]+)"""".r

    def extractValue(pattern: Regex, text: String): Option[String] = {
      pattern.findFirstMatchIn(text).map(_.group(1))
    }

    // Extract each field from the JSON response.
    val displayName = extractValue(displayNamePattern, response).getOrElse("N/A")
    val nationality = extractValue(nationalityPattern, response).map(_.toInt).getOrElse(0)
    val position = extractValue(positionPattern, response).map(_.toInt).getOrElse(0)
    val headshot = extractValue(headshotPattern, response).getOrElse("N/A")
    val dobStr = extractValue(dobPattern, response).getOrElse("")

    // Calculate age using the date of birth.
    val age = if (dobStr.nonEmpty) {
      val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
      val birthDate = LocalDate.parse(dobStr, formatter)
      Period.between(birthDate, LocalDate.now()).getYears
    } else 0

    // Print the extracted values.
    println(s"Display Name: $displayName")
    println(s"Nationality: $nationality")
    println(s"Position: $position")
    println(s"Headshot: $headshot")  
    println(s"Age: $age")
  } catch {
    case e: Exception =>
      println("An error occurred while fetching data:")
      println(e.getMessage)
  }
}

Display Name: Virgil van Dijk
Nationality: 38
Position: 25
Headshot: https:\/\/cdn.sportmonks.com\/images\/soccer\/players\/15\/1743.png
Age: 33

Now that we have a few personal details of our player of interest, we shall determine a suitable data profile. For instance, while the focus will be on goals and assists for a player in an attacking position, blocked shots, interceptions, and other key defensive metrics will paint a much clearer picture for a defender such as Virgil van Dijk.

Nevertheless, Sportmonks Football API provides all relevant statistics for players irrespective of their positions. For today’s exercise, we will focus on the current season’s stats for our player of choice, Virgil van Dijk.

Among them will be tackles, yellow cards, fouls drawn, blocked shots, clearances, total duels, duels won and dribbled past. While this is not an exhaustive list, it will do justice for this exercise.

STEP 4 – Retrieve squad stats

Here’s the interesting part: making our thoughts come to reality. Before we can retrieve the details for our player of choice, we shall retrieve the current season’s stats for all Liverpool players using the URL below.

https://api.sportmonks.com/v3/football/squads/teams/Team_ID?api_token=API_Token&include=player.statistics.details&filters=playerStatisticSeasons:Seasonid

Replacing Team_ID with 8 for Liverpool and Season ID with 23614, which represents the 2024/25 Premier League season, on our browser, here below is our response.

{
  "data": [
    {
      "id": 967671,
      "transfer_id": null,
      "player_id": 9606060,
      "team_id": 8,
      "position_id": 24,
      "detailed_position_id": 24,
      "start": "2022-07-01",
      "end": "2025-06-30",
      "captain": false,
      "jersey_number": 56,
      "player": {
        "id": 9606060,
        "sport_id": 1,
        "country_id": 245,
        "nationality_id": 245,
        "city_id": null,
        "position_id": 24,
        "detailed_position_id": 24,
        "type_id": 24,
        "common_name": "V. Jaroš",
        "firstname": "Vítězslav",
        "lastname": "Jaroš",
        "name": "Vítězslav Jaroš",
        "display_name": "Vítězslav Jaroš",
        "image_path": "https://cdn.sportmonks.com/images/soccer/players/12/9606060.png",
        "height": 190,
        "weight": null,
        "date_of_birth": "2001-07-23",
        "gender": "male",
        "statistics": [
          {
            "id": 1429697901,
            "player_id": 9606060,
            "team_id": 8,
            "season_id": 23614,
            "has_values": true,
            "position_id": 24,
            "jersey_number": 56,
            "details": [
              {
                "id": 38668536,
                "player_statistic_id": 1429697901,
                "type_id": 57,
                "value": {
                  "total": 1
                }
              },
              {
                "id": 38668543,
                "player_statistic_id": 1429697901,
                "type_id": 59,
                "value": {
                  "in": 1,
                  "out": 0
                }
              },
              {
                "id": 38668519,
                "player_statistic_id": 1429697901,
                "type_id": 80,
                "value": {
                  "total": 6
                }
              },
              {
                "id": 38668500,
                "player_statistic_id": 1429697901,
                "type_id": 101,
                "value": {
                  "total": 1
                }
              },
              {
                "id": 38668540,
                "player_statistic_id": 1429697901,
                "type_id": 104,
                "value": {
                  "total": 1
                }
              },
              {
                "id": 38668487,
                "player_statistic_id": 1429697901,
                "type_id": 116,
                "value": {
                  "total": 4
                }
              },
              {
                "id": 38668530,
                "player_statistic_id": 1429697901,
                "type_id": 118,
                "value": {
                  "average": 7.24,
                  "highest": 7.24,
                  "lowest": 7.24
                }
              },
              {
                "id": 38668515,
                "player_statistic_id": 1429697901,
                "type_id": 119,
                "value": {
                  "total": 11
                }
              },
              {
                "id": 38668512,
                "player_statistic_id": 1429697901,
                "type_id": 122,
                "value": {
                  "total": 6
                }
              },
              {
                "id": 38668514,
                "player_statistic_id": 1429697901,
                "type_id": 123,
                "value": {
                  "total": 4
                }
              },
              {
                "id": 38668498,
                "player_statistic_id": 1429697901,
                "type_id": 194,
                "value": {
                  "total": 1,
                  "home": 0,
                  "away": 1
                }
              },
              {
                "id": 39280019,
                "player_statistic_id": 1429697901,
                "type_id": 214,
                "value": {
                  "total": 1
                }
              },
              {
                "id": 38668489,
                "player_statistic_id": 1429697901,
                "type_id": 321,
                "value": {
                  "total": 1
                }
              },
              {
                "id": 38490528,
                "player_statistic_id": 1429697901,
                "type_id": 323,
                "value": {
                  "total": 9
                }
              },
              {
                "id": 38668485,
                "player_statistic_id": 1429697901,
                "type_id": 1584,
                "value": {
                  "total": 66.67
                }
              }
            ]
          }
        ]
      }
    },
    {
      "id": 721026,
      "transfer_id": 229892,
      "player_id": 785998,
      "team_id": 8,
      "position_id": 26,
      "detailed_position_id": 153,
      "start": "2023-07-02",
      "end": "2028-06-30",
      "captain": false,
      "jersey_number": 8,
      "player": {
        "id": 785998,
        "sport_id": 1,
        "country_id": 674,
        "nationality_id": 674,
        "city_id": null,
        "position_id": 26,
        "detailed_position_id": 153,
        "type_id": 26,
        "common_name": "D. Szoboszlai",
        "firstname": "Dominik",
        "lastname": "Szoboszlai",
        "name": "Dominik Szoboszlai",
        "display_name": "Dominik Szoboszlai",
        "image_path": "https://cdn.sportmonks.com/images/soccer/players/14/785998.png",
        "height": 187,
        "weight": 74,
        "date_of_birth": "2000-10-25",
        "gender": "male",
        "statistics": [
          {
            "id": 1324089037,
            "player_id": 785998,
            "team_id": 8,
            "season_id": 23614,
            "has_values": true,
            "position_id": 26,
            "jersey_number": 8,
            "details": [
              {
                "id": 38179753,
                "player_statistic_id": 1324089037,
                "type_id": 41,
                "value": {
                  "total": 13
                }
              },
              {
                "id": 37861717,
                "player_statistic_id": 1324089037,
                "type_id": 42,
                "value": {
                  "total": 51
                }
              },
              {
                "id": 44045189,
                "player_statistic_id": 1324089037,
                "type_id": 51,
                "value": {
                  "total": 3
                }
              },
              {
                "id": 39279978,
                "player_statistic_id": 1324089037,
                "type_id": 52,
                "value": {
                  "total": 4,
                  "goals": 4,
                  "penalties": 0
                }
              },
              {
                "id": 37861499,
                "player_statistic_id": 1324089037,
                "type_id": 56,
                "value": {
                  "total": 33
                }
              },
              {
                "id": 37861728,
                "player_statistic_id": 1324089037,
                "type_id": 58,
                "value": {
                  "total": 22
                }
              },
              {
                "id": 38490587,
                "player_statistic_id": 1324089037,
                "type_id": 59,
                "value": {
                  "in": 5,
                  "out": 6
                }
              },
              {
                "id": 44187185,
                "player_statistic_id": 1324089037,
                "type_id": 64,
                "value": {
                  "total": 1
                }
              },
              {
                "id": 37861752,
                "player_statistic_id": 1324089037,
                "type_id": 78,
                "value": {
                  "total": 27
                }
              },
              {
                "id": 38179612,
                "player_statistic_id": 1324089037,
                "type_id": 79,
                "value": {
                  "total": 3
                }
              },
              {
                "id": 37861616,
                "player_statistic_id": 1324089037,
                "type_id": 80,
                "value": {
                  "total": 908
                }
              },
              {
                "id": 38068531,
                "player_statistic_id": 1324089037,
                "type_id": 84,
                "value": {
                  "total": 6,
                  "home": 4,
                  "away": 2
                }
              },
              {
                "id": 38597886,
                "player_statistic_id": 1324089037,
                "type_id": 86,
                "value": {
                  "total": 17
                }
              },
              {
                "id": 38373378,
                "player_statistic_id": 1324089037,
                "type_id": 88,
                "value": {
                  "total": 18
                }
              },
              {
                "id": 38068452,
                "player_statistic_id": 1324089037,
                "type_id": 94,
                "value": {
                  "total": 15
                }
              },
              {
                "id": 37861515,
                "player_statistic_id": 1324089037,
                "type_id": 96,
                "value": {
                  "total": 17
                }
              },
              {
                "id": 38068444,
                "player_statistic_id": 1324089037,
                "type_id": 97,
                "value": {
                  "total": 7
                }
              },
              {
                "id": 37861779,
                "player_statistic_id": 1324089037,
                "type_id": 98,
                "value": {
                  "total": 29
                }
              },
              {
                "id": 38179604,
                "player_statistic_id": 1324089037,
                "type_id": 99,
                "value": {
                  "total": 11
                }
              },
              {
                "id": 38179685,
                "player_statistic_id": 1324089037,
                "type_id": 100,
                "value": {
                  "total": 9
                }
              },
              {
                "id": 37861343,
                "player_statistic_id": 1324089037,
                "type_id": 101,
                "value": {
                  "total": 6
                }
              },
              {
                "id": 37861431,
                "player_statistic_id": 1324089037,
                "type_id": 105,
                "value": {
                  "total": 171
                }
              },
              {
                "id": 37861450,
                "player_statistic_id": 1324089037,
                "type_id": 106,
                "value": {
                  "total": 76
                }
              },
              {
                "id": 37861181,
                "player_statistic_id": 1324089037,
                "type_id": 107,
                "value": {
                  "total": 17
                }
              },
              {
                "id": 37861407,
                "player_statistic_id": 1324089037,
                "type_id": 108,
                "value": {
                  "total": 28
                }
              },
              {
                "id": 37861418,
                "player_statistic_id": 1324089037,
                "type_id": 109,
                "value": {
                  "total": 16
                }
              },
              {
                "id": 38490533,
                "player_statistic_id": 1324089037,
                "type_id": 110,
                "value": {
                  "total": 21
                }
              },
              {
                "id": 37861171,
                "player_statistic_id": 1324089037,
                "type_id": 116,
                "value": {
                  "total": 780
                }
              },
              {
                "id": 37861566,
                "player_statistic_id": 1324089037,
                "type_id": 117,
                "value": {
                  "total": 37
                }
              },
              {
                "id": 37861677,
                "player_statistic_id": 1324089037,
                "type_id": 118,
                "value": {
                  "average": 7.27,
                  "highest": 9.08,
                  "lowest": 6.43
                }
              },
              {
                "id": 37861599,
                "player_statistic_id": 1324089037,
                "type_id": 119,
                "value": {
                  "total": 1819
                }
              },
              {
                "id": 37861585,
                "player_statistic_id": 1324089037,
                "type_id": 122,
                "value": {
                  "total": 59
                }
              },
              {
                "id": 37861591,
                "player_statistic_id": 1324089037,
                "type_id": 123,
                "value": {
                  "total": 37
                }
              },
              {
                "id": 44606982,
                "player_statistic_id": 1324089037,
                "type_id": 124,
                "value": {
                  "total": 2
                }
              },
              {
                "id": 44757181,
                "player_statistic_id": 1324089037,
                "type_id": 125,
                "value": {
                  "total": 1
                }
              },
              {
                "id": 37861325,
                "player_statistic_id": 1324089037,
                "type_id": 194,
                "value": {
                  "total": 10,
                  "home": 4,
                  "away": 6
                }
              },
              {
                "id": 39280094,
                "player_statistic_id": 1324089037,
                "type_id": 214,
                "value": {
                  "total": 18
                }
              },
              {
                "id": 39279940,
                "player_statistic_id": 1324089037,
                "type_id": 215,
                "value": {
                  "total": 6
                }
              },
              {
                "id": 39280021,
                "player_statistic_id": 1324089037,
                "type_id": 216,
                "value": {
                  "total": 1
                }
              },
              {
                "id": 37861218,
                "player_statistic_id": 1324089037,
                "type_id": 321,
                "value": {
                  "total": 25
                }
              },
              {
                "id": 37861577,
                "player_statistic_id": 1324089037,
                "type_id": 322,
                "value": {
                  "total": 20
                }
              },
              {
                "id": 38668497,
                "player_statistic_id": 1324089037,
                "type_id": 323,
                "value": {
                  "total": 5
                }
              },
              {
                "id": 37861261,
                "player_statistic_id": 1324089037,
                "type_id": 580,
                "value": {
                  "total": 23
                }
              },
              {
                "id": 38597852,
                "player_statistic_id": 1324089037,
                "type_id": 581,
                "value": {
                  "total": 8
                }
              },
              {
                "id": 37861156,
                "player_statistic_id": 1324089037,
                "type_id": 1584,
                "value": {
                  "total": 85.9
                }
              },
              {
                "id": 37861482,
                "player_statistic_id": 1324089037,
                "type_id": 5304,
                "value": {
                  "expected": 6.0905,
                  "actual": 4,
                  "difference": -2.091
                }
              },
              {
                "id": 39280045,
                "player_statistic_id": 1324089037,
                "type_id": 9676,
                "value": {
                  "average": "0.16"
                }
              },
              {
                "id": 37861387,
                "player_statistic_id": 1324089037,
                "type_id": 27255,
                "value": {
                  "crosses_blocked": 18
                }
              }
            ]
          }
        ]
      }
    },...

STEP 5 – Extracting our player’s data profile

Virgil-van-Dijk-player-data-profilesAs you can see from the response in step 4, all player data details were retrieved. However, our interest is focused only on Virgil van Dijk.

Our piece of Scala code will help us achieve this.

Looking at our player stats documentation and using the type IDs for Tackles (78), Yellow Cards (84), Fouls Drawn (96), Blocked Shots (97), Clearances (101), Total Duels (105), Duels Won (106), and Dribbled Past (110), we can retrieve the required details.

import scala.io.Source
import java.net.URL
import java.nio.charset.CodingErrorAction
import scala.io.Codec
import scala.util.matching.Regex
import java.time.{LocalDate, Period}
import java.time.format.DateTimeFormatter

object FilterDataById extends App {
  
  val apiToken = "API Token" // Replace with your API Token
  val teamId = "8"
  val playerId = 1743
  val url = s"https://api.sportmonks.com/v3/football/squads/teams/$teamId?api_token=$apiToken&include=player.statistics.details&filters=playerStatisticSeasons:23614"

  // Handle character encoding issues.
  implicit val codec: Codec = Codec("UTF-8")
  codec.onMalformedInput(CodingErrorAction.REPLACE)
  codec.onUnmappableCharacter(CodingErrorAction.REPLACE)

  try {
    // Retrieve the JSON response as a string.
    val response = Source.fromURL(new URL(url)).mkString

    // Regex to extract the entire player block for the given playerId (including statistics details)
    val playerIdRegex: Regex =
      s""""player"\\s*:\\s*\\{[^}]*"id"\\s*:\\s*$playerId[^}]*"statistics"\\s*:\\s*\\[.*?\\]\\s*\\}""".r

    playerIdRegex.findFirstMatchIn(response) match {
      case Some(matchedPlayer) =>
        val playerBlock = matchedPlayer.group(0)

        // Extract the player's display name
        val displayNameRegex: Regex = """"display_name"\s*:\s*"([^"]+)"""".r
        val displayName = displayNameRegex.findFirstMatchIn(playerBlock)
          .map(_.group(1))
          .getOrElse("Unknown")

        // Extract the player's image path
        val imagePathRegex: Regex = """"image_path"\s*:\s*"([^"]+)"""".r
        val imagePath = imagePathRegex.findFirstMatchIn(playerBlock)
          .map(_.group(1))
          .getOrElse("Unknown")

        // Extract the player's height
        val heightRegex: Regex = """"height"\s*:\s*(\d+)""".r
        val height = heightRegex.findFirstMatchIn(playerBlock)
          .map(_.group(1))
          .getOrElse("Unknown")

        // Extract the player's date of birth and calculate age
        val dobRegex: Regex = """"date_of_birth"\s*:\s*"(\d{4}-\d{2}-\d{2})"""".r
        val dobStr = dobRegex.findFirstMatchIn(playerBlock)
          .map(_.group(1))
          .getOrElse("1900-01-01")
        val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
        val birthDate = LocalDate.parse(dobStr, formatter)
        val age = Period.between(birthDate, LocalDate.now()).getYears

        // Print player's basic information
        println(s"Image Path: $imagePath")
        println(s"Display Name: $displayName")
        println(s"Height: $height cm")
        println(s"Age: $age years")
        println("Club: Liverpool")

        // Regex to extract specific type_id values from the statistics details.
        val typeIdRegex: Regex =
          """"type_id"\s*:\s*(\d+)\s*,\s*"value"\s*:\s*\{[^}]*"total"\s*:\s*(\d+)""".r

        val typeIdLabels = Map(
          "78" -> "Tackles",
          "84" -> "Yellow Cards",
          "96" -> "Fouls Drawn",
          "97" -> "Blocked Shots",
          "101" -> "Clearances",
          "105" -> "Total Duels",
          "106" -> "Duels Won",
          "110" -> "Dribbled Past"
        )

        val extractedValues = typeIdRegex.findAllMatchIn(playerBlock).collect {
          case m if typeIdLabels.contains(m.group(1)) =>
            s"${typeIdLabels(m.group(1))}: ${m.group(2)}"
        }.toList

        if (extractedValues.nonEmpty) {
          println("\n2024/25 Premier League Season.")
          extractedValues.foreach(println)
        } else {
          println(s"\nNo matching statistics found for player $playerId.")
        }

      case None =>
        println(s"No player found with id $playerId.")
    }
  } catch {
    case e: Exception =>
      println("An error occurred while fetching data:")
      println(e.getMessage)
  }
}
Image Path: https:\/\/cdn.sportmonks.com\/images\/soccer\/players\/15\/1743.png
Display Name: Virgil van Dijk
Height: 195 cm
Age: 33 years
Club: Liverpool

2024/25 Premier League Season.
Tackles: 32
Yellow Cards: 3
Fouls Drawn: 9
Blocked Shots: 12
Clearances: 131
Total Duels: 184
Duels Won: 128
Dribbled Past: 7

STEP 6 – Create Soccer player data profiles by positions

As you can see from the previous example, we can easily replace club and player IDs to retrieve the details we need for a specific player from any club of choice.

However, let’s assume we wish to display data profiles of all defenders from Liverpool. Head over to the documentation to select the required position ID for defenders (25).

In our new piece of code, we shall use the selected ID to retrieve player data profiles for all defenders in Liverpool Football Club for the 2024/25 Premier League season.

import scala.io.Source
import java.net.URL
import java.nio.charset.CodingErrorAction
import scala.io.Codec
import scala.util.matching.Regex
import java.time.{LocalDate, Period}
import java.time.format.DateTimeFormatter

object FilterDataByPosition extends App {
  // API details
  val apiToken = "API Token"
  val teamId = "8"
  val url = s"https://api.sportmonks.com/v3/football/squads/teams/$teamId?api_token=$apiToken&include=player.statistics.details&filters=playerStatisticSeasons:23614"

  // Handle character encoding issues.
  implicit val codec: Codec = Codec("UTF-8")
  codec.onMalformedInput(CodingErrorAction.REPLACE)
  codec.onUnmappableCharacter(CodingErrorAction.REPLACE)

  try {
    // Retrieve the JSON response as a string.
    val response = Source.fromURL(new URL(url)).mkString

    // Regex to extract all players with position_id 25
    val playerRegex: Regex =
      """"player"\s*:\s*\{[^}]*"position_id"\s*:\s*25[^}]*"statistics"\s*:\s*\[.*?\]\s*\}""".r

    val players = playerRegex.findAllMatchIn(response).toList

    if (players.nonEmpty) {
      players.foreach { matchedPlayer =>
        val playerBlock = matchedPlayer.group(0)

        // Extract the player's display name
        val displayNameRegex: Regex = """"display_name"\s*:\s*"([^"]+)""".r
        val displayName = displayNameRegex.findFirstMatchIn(playerBlock)
          .map(_.group(1))
          .getOrElse("Unknown")

        // Extract the player's image path
        val imagePathRegex: Regex = """"image_path"\s*:\s*"([^"]+)""".r
        val imagePath = imagePathRegex.findFirstMatchIn(playerBlock)
          .map(_.group(1))
          .getOrElse("Unknown")

        // Extract the player's height
        val heightRegex: Regex = """"height"\s*:\s*(\d+)""".r
        val height = heightRegex.findFirstMatchIn(playerBlock)
          .map(_.group(1))
          .getOrElse("Unknown")

        // Extract the player's date of birth and calculate age
        val dobRegex: Regex = """"date_of_birth"\s*:\s*"(\d{4}-\d{2}-\d{2})""".r
        val dobStr = dobRegex.findFirstMatchIn(playerBlock)
          .map(_.group(1))
          .getOrElse("1900-01-01")
        val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
        val birthDate = LocalDate.parse(dobStr, formatter)
        val age = Period.between(birthDate, LocalDate.now()).getYears

        // Print player's basic information
        println(s"\nImage Path: $imagePath")
        println(s"Display Name: $displayName")
        println(s"Height: $height cm")
        println(s"Age: $age years")
        println("Club: Liverpool")

        // Regex to extract specific type_id values from the statistics details.
        val typeIdRegex: Regex =
          """"type_id"\s*:\s*(\d+)\s*,\s*"value"\s*:\s*\{[^}]*"total"\s*:\s*(\d+)""".r

        val typeIdLabels = Map(
          "78" -> "Tackles",
          "84" -> "Yellow Cards",
          "96" -> "Fouls Drawn",
          "97" -> "Blocked Shots",
          "101" -> "Clearances",
          "105" -> "Total Duels",
          "106" -> "Duels Won",
          "110" -> "Dribbled Past"
        )

        val extractedValues = typeIdRegex.findAllMatchIn(playerBlock).collect {
          case m if typeIdLabels.contains(m.group(1)) =>
            s"${typeIdLabels(m.group(1))}: ${m.group(2)}"
        }.toList

        if (extractedValues.nonEmpty) {
          println("\n2024/25 Premier League Season.")
          extractedValues.foreach(println)
        } else {
          println("\nNo matching statistics found for this player.")
        }
      }
    } else {
      println("No players found with position_id 25.")
    }
  } catch {
    case e: Exception =>
      println("An error occurred while fetching data:")
      println(e.getMessage)
  }
}

Image Path: https:\/\/cdn.sportmonks.com\/images\/soccer\/players\/22\/1078.png
Display Name: Andrew Robertson
Height: 178 cm
Age: 30 years
Club: Liverpool

2024/25 Premier League Season.
Tackles: 34
Yellow Cards: 3
Fouls Drawn: 6
Blocked Shots: 4
Clearances: 35
Total Duels: 99
Duels Won: 47
Dribbled Past: 16

Image Path: https:\/\/cdn.sportmonks.com\/images\/soccer\/players\/13\/1453.png
Display Name: Joe Gomez
Height: 188 cm
Age: 27 years
Club: Liverpool

2024/25 Premier League Season.
Tackles: 13
Yellow Cards: 1
Fouls Drawn: 3
Blocked Shots: 6
Clearances: 20
Total Duels: 38
Duels Won: 25
Dribbled Past: 5

Image Path: https:\/\/cdn.sportmonks.com\/images\/soccer\/players\/12\/100556.png
Display Name: Ibrahima Konate
Height: 194 cm
Age: 25 years
Club: Liverpool

2024/25 Premier League Season.
Tackles: 30
Yellow Cards: 5
Fouls Drawn: 13
Blocked Shots: 12
Clearances: 82
Total Duels: 149
Duels Won: 102
Dribbled Past: 9

Image Path: https:\/\/cdn.sportmonks.com\/images\/soccer\/players\/15\/1743.png
Display Name: Virgil van Dijk
Height: 195 cm
Age: 33 years
Club: Liverpool

2024/25 Premier League Season.
Tackles: 32
Yellow Cards: 3
Fouls Drawn: 9
Blocked Shots: 12
Clearances: 131
Total Duels: 184
Duels Won: 128
Dribbled Past: 7

Image Path: https:\/\/cdn.sportmonks.com\/images\/soccer\/players\/27\/37259163.png
Display Name: Jarell Quansah
Height: 190 cm
Age: 22 years
Club: Liverpool

2024/25 Premier League Season.
Tackles: 9
Yellow Cards: 1
Fouls Drawn: 1
Blocked Shots: 4
Clearances: 10
Total Duels: 32
Duels Won: 16
Dribbled Past: 1

Image Path: https:\/\/cdn.sportmonks.com\/images\/soccer\/players\/29\/1917.png
Display Name: Trent Alexander-Arnold
Height: 175 cm
Age: 26 years
Club: Liverpool

2024/25 Premier League Season.
Tackles: 61
Yellow Cards: 4
Fouls Drawn: 6
Blocked Shots: 8
Clearances: 40
Total Duels: 175
Duels Won: 77
Dribbled Past: 51

Image Path: https:\/\/cdn.sportmonks.com\/images\/soccer\/players\/3\/37316835.png
Display Name: Conor Bradley
Height: 181 cm
Age: 21 years
Club: Liverpool

2024/25 Premier League Season.
Tackles: 6
Yellow Cards: 2
Fouls Drawn: 5
Clearances: 12
Total Duels: 40
Duels Won: 19
Dribbled Past: 8

Image Path: https:\/\/cdn.sportmonks.com\/images\/soccer\/players\/19\/84627.png
Display Name: Konstantinos Tsimikas
Height: 179 cm
Age: 28 years
Club: Liverpool

2024/25 Premier League Season.
Tackles: 13
Yellow Cards: 1
Fouls Drawn: 1
Blocked Shots: 2
Clearances: 11
Total Duels: 35
Duels Won: 21
Dribbled Past: 3

Conclusion

Are you up for the challenge? Using a conventional profile for an attacker that displays well-known metrics, such as shots-on-target (86), assists (79), minutes-played (119), goals (52), and shots-off-target (41), you can achieve the same thing by editing the correct sections of our Scala code.

As you can see, with minimal effort, a wealth of statistical data can be harnessed from Sportmonks Football API, using the right tools. You can easily build soccer player data profiles for one or more players in one or more roles for one or more clubs.

What are you waiting for? Give your app the proper boost it deserves with deep player statistics.

Written by Wesley Van Rooij

Wesley van Rooij is a marketing and football expert with over 5 years of industry experience. His comprehensive knowledge of the Sportmonks Football API and a focused approach to APIs in the Sports Data industry allow him to offer insights and support to enthusiasts and businesses. His outstanding marketing and communication skills and technical writing expertise enable him to empathise with developers. He understands their needs and challenges to facilitate the development of cutting-edge football applications that stand out in the market.