TUTORIAL

    How to Get Football Player Stats via API: A Complete Developer Guide

    Learn how to fetch player statistics from a football API. Includes Python and JavaScript examples for goals, assists, appearances, and more. Free trial available.

    Last updated: March 27, 20268 min read

    Player statistics are the backbone of fantasy football apps, scouting tools, analytics dashboards, and sports media products. Goals, assists, appearances, minutes played, cards, shots on target - this data drives everything from player comparison widgets to machine learning models that predict transfer values.

    This guide shows you how to fetch football player stats from an API using Python and JavaScript. We will cover searching for players, fetching season stats, bulk-fetching all players in a competition, and caching strategies that keep your app fast without burning through your request quota. All examples use TheStatsAPI, which includes 84,000+ player profiles with detailed statistics across 1,196 competitions.

    What Player Stats Are Available

    A good football API provides more than just goals and assists. Here is what you can expect from TheStatsAPI's player statistics endpoints:

    • Goals - total goals scored in a season or competition
    • Assists - total assists provided
    • Appearances - number of matches played (starts + substitute appearances)
    • Minutes played - total minutes on the pitch
    • Yellow cards and red cards - disciplinary record
    • Shots and shots on target - shooting volume and accuracy
    • Passes and pass accuracy - distribution metrics
    • Tackles and interceptions - defensive contributions
    • Clean sheets - for goalkeepers and defenders

    These stats are broken down by season and competition, so you can track a player's performance across different leagues and time periods. With 20+ years of historical data, you can also pull career-spanning statistics for trend analysis.

    Fetching Season Stats in Python

    Let's start by fetching stats for a specific player. You will need the player's ID, which you can get from the search endpoint (covered in the next section).

    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 stats for a specific player
    player_id = 42  # Replace with an actual player ID
    response = requests.get(
        f"{BASE_URL}/football/players/{player_id}/stats",
        headers=headers
    )
    
    if response.status_code == 200:
        data = response.json()
        stats = data.get("data", {})
    
        print(f"Player: {stats.get('name', 'Unknown')}")
        print(f"Team: {stats.get('team', {}).get('name', 'N/A')}")
        print(f"Position: {stats.get('position', 'N/A')}")
        print()
    
        for season_stat in stats.get("seasons", []):
            season = season_stat["season"]
            competition = season_stat["competition"]["name"]
            goals = season_stat.get("goals", 0)
            assists = season_stat.get("assists", 0)
            appearances = season_stat.get("appearances", 0)
            minutes = season_stat.get("minutes_played", 0)
            yellows = season_stat.get("yellow_cards", 0)
            reds = season_stat.get("red_cards", 0)
    
            print(f"{season} | {competition}")
            print(f"  Apps: {appearances} | Goals: {goals} | Assists: {assists}")
            print(f"  Minutes: {minutes} | YC: {yellows} | RC: {reds}")
            print()
    else:
        print(f"Error: {response.status_code} - {response.text}")
    

    This gives you a complete statistical breakdown for each season the player has participated in. You can filter the results on your end by season year or competition to display exactly what your application needs.

    Searching for a Player by Name

    You rarely know a player's ID upfront. The search endpoint lets you find players by name:

    import requests
    
    API_KEY = "your_api_key_here"
    BASE_URL = "https://api.thestatsapi.com/api"
    
    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Accept": "application/json"
    }
    
    # Search for a player
    search_term = "Haaland"
    response = requests.get(
        f"{BASE_URL}/football/players",
        headers=headers,
        params={"search": search_term}
    )
    
    if response.status_code == 200:
        data = response.json()
        players = data.get("data", [])
    
        print(f"Found {len(players)} players matching '{search_term}':\n")
    
        for player in players:
            pid = player["id"]
            name = player["name"]
            team = player.get("team", {}).get("name", "N/A")
            nationality = player.get("nationality", "N/A")
            position = player.get("position", "N/A")
            print(f"  ID: {pid} | {name} | {team} | {position} | {nationality}")
    else:
        print(f"Error: {response.status_code}")
    

    The search is case-insensitive and matches against the player's full name. Use the returned id to then fetch that player's detailed statistics.

    Combining Search and Stats

    Here is a practical function that searches for a player and immediately fetches their stats:

    def get_player_stats_by_name(name):
        """Search for a player and return their stats."""
        # Step 1: Search
        search_response = requests.get(
            f"{BASE_URL}/football/players",
            headers=headers,
            params={"search": name}
        )
        players = search_response.json().get("data", [])
    
        if not players:
            print(f"No players found for '{name}'")
            return None
    
        # Use the first match
        player = players[0]
        player_id = player["id"]
        print(f"Found: {player['name']} (ID: {player_id})")
    
        # Step 2: Fetch stats
        stats_response = requests.get(
            f"{BASE_URL}/football/players/{player_id}/stats",
            headers=headers
        )
        return stats_response.json().get("data", {})
    
    
    stats = get_player_stats_by_name("Salah")
    

    Bulk Fetching All Players in a Competition

    If you are building a fantasy app or a comprehensive stats database, you need all players in a league - not just one at a time. The players endpoint supports filtering by competition and pagination:

    import requests
    import time
    
    API_KEY = "your_api_key_here"
    BASE_URL = "https://api.thestatsapi.com/api"
    
    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Accept": "application/json"
    }
    
    def fetch_all_players(competition_id):
        """Fetch all players in a competition, handling pagination."""
        all_players = []
        page = 1
    
        while True:
            response = requests.get(
                f"{BASE_URL}/football/players",
                headers=headers,
                params={
                    "competition_id": competition_id,
                    "page": page
                }
            )
    
            if response.status_code == 429:
                print("Rate limited - waiting 60 seconds...")
                time.sleep(60)
                continue
    
            data = response.json()
            players = data.get("data", [])
            all_players.extend(players)
    
            last_page = data["meta"]["last_page"]
            print(f"Page {page}/{last_page} - {len(all_players)} players so far")
    
            if page >= last_page:
                break
    
            page += 1
            time.sleep(2)  # Respect rate limits
    
        return all_players
    
    
    # Fetch all Premier League players
    players = fetch_all_players(competition_id=1)
    print(f"\nTotal players: {len(players)}")
    

    This approach respects rate limits by adding a 2-second delay between requests and automatically retries on 429 errors. For the Starter plan (30 requests per minute), this keeps you safely under the limit.

    JavaScript Example

    Here is a complete JavaScript version using fetch in Node.js 18+:

    const API_KEY = "your_api_key_here";
    const BASE_URL = "https://api.thestatsapi.com/api";
    
    const headers = {
      Authorization: `Bearer ${API_KEY}`,
      Accept: "application/json",
    };
    
    async function searchPlayer(name) {
      const url = new URL(`${BASE_URL}/football/players`);
      url.searchParams.set("search", name);
    
      const response = await fetch(url, { headers });
      if (!response.ok) throw new Error(`HTTP ${response.status}`);
    
      const data = await response.json();
      return data.data;
    }
    
    async function getPlayerStats(playerId) {
      const response = await fetch(
        `${BASE_URL}/football/players/${playerId}/stats`,
        { headers }
      );
      if (!response.ok) throw new Error(`HTTP ${response.status}`);
    
      const data = await response.json();
      return data.data;
    }
    
    async function main() {
      // Search for a player
      const results = await searchPlayer("De Bruyne");
      if (results.length === 0) {
        console.log("No players found");
        return;
      }
    
      const player = results[0];
      console.log(`Found: ${player.name} (ID: ${player.id})\n`);
    
      // Fetch their stats
      const stats = await getPlayerStats(player.id);
    
      for (const season of stats.seasons || []) {
        console.log(`${season.season} | ${season.competition.name}`);
        console.log(
          `  Apps: ${season.appearances} | Goals: ${season.goals} | Assists: ${season.assists}`
        );
        console.log(
          `  Minutes: ${season.minutes_played} | YC: ${season.yellow_cards} | RC: ${season.red_cards}`
        );
        console.log();
      }
    }
    
    main().catch(console.error);
    

    Caching Strategies

    Player statistics do not change every second. A player's season goals total only updates when a match finishes, and TheStatsAPI's post-match data arrives within 1-2 hours of full time. This means aggressive caching is both safe and smart.

    Cache duration recommendations

    • Player search results: Cache for 24 hours. Player names and team affiliations rarely change mid-season.
    • Season statistics: Cache for 6-12 hours during the season, 24+ hours during the off-season. Stats only change after matches, and most leagues play 1-2 matches per week per team.
    • Player profiles (bio, nationality, position): Cache for 7 days. This data almost never changes.

    Simple in-memory cache in Python

    import time
    
    _cache = {}
    
    def cached_get(url, headers, params=None, ttl=21600):
        """Simple cache wrapper. ttl is in seconds (default 6 hours)."""
        cache_key = f"{url}:{params}"
    
        if cache_key in _cache:
            cached_at, data = _cache[cache_key]
            if time.time() - cached_at < ttl:
                return data
    
        response = requests.get(url, headers=headers, params=params)
        data = response.json()
        _cache[cache_key] = (time.time(), data)
        return data
    

    For production applications, use Redis or Memcached instead of an in-memory dictionary. The principle is the same: store the response, check the TTL before making a new request, and invalidate when needed.

    Cache math

    On the Starter plan (100,000 requests per month), caching player stats with a 6-hour TTL means each player's stats are fetched at most 4 times per day. For 500 players, that is 2,000 requests per day or roughly 60,000 per month - well within your quota, with room for search queries and other endpoints.

    Frequently Asked Questions

    How many players does TheStatsAPI cover?

    TheStatsAPI includes over 84,000 player profiles across 1,196 competitions. This covers all major European leagues, South American competitions, Asian leagues, and many lower divisions. Players are linked to their teams and competition history, so you can track transfers and career trajectories.

    Can I get historical player stats from previous seasons?

    Yes. TheStatsAPI provides 20+ years of historical data, including player statistics from past seasons. You can fetch a player's stats and receive their full career statistical history, broken down by season and competition. This is especially useful for building prediction models and career comparison tools.

    Are player stats available during a live match?

    TheStatsAPI provides post-match data, typically updated within 1-2 hours after full time. It does not offer live in-play statistics. If you need real-time player stats during a match (live goals, live assists), you would need to supplement TheStatsAPI with a live data provider. For most applications - fantasy leagues, stat dashboards, analytics tools - post-match stats are more than sufficient.


    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. Start your trial at thestatsapi.com and build your player stats integration today.

    Start building today

    Ready to Power Your Sports App?

    Start your 7-day free trial. All endpoints included on every plan.

    Cancel anytime
    7-day free trial
    Setup in 5 minutes