Free Sports API

 Support
The free JSON sports API will always remain free at point of access for basic sports data.
All example links should be testable in the browser for v1.
Here are some php, javascript, python code examples to get you going.

 Test API Keys
Free users can use the test API key "3" during development of your app or for educational use.
If you have paid for a premium key, just replace "3" with your "API KEY" in the URL.

 API Limits
The Rate limiter will kick in if you make over 100 requests per minute on our API with a 429 response.

 V1 API vs V2
Version 1 of the API is now 7 years old and very stable. Most of the API is also free to use.
V2 is a more modern implimentation with API key header authentication and simpler descriptive calls.
Both use the same data, but may difer in structure. V2 is only available to Patreon subscribers

 Premium API
$7 monthly Patreon supporters get a dedicated production API key
including 2min Livescores, Video highlights and all other upgraded features.
You must be registered on TheSportsDB and a supporter on Patreon
Once signed up you can find your API key on the user page.


 Contact
Email: <PRESIDIO_ANONYMIZED_EMAIL_ADDRESS> - Please state if you are a Patreon Supporter

seperator bar


V1 API
 Search

Search for team by name
/api/v1/json/3/searchteams.php?t=Arsenal

Search for team short code
/api/v1/json/3/searchteams.php?sname=ARS

Search for all players from team patreon icon
/api/v1/json/3/searchplayers.php?t=Arsenal

Search for players by name
/api/v1/json/3/searchplayers.php?p=Danny_Welbeck
/api/v1/json/{APIKEY}/searchplayers.php?t={TeamName}&p={Playername}

Search for event by event name
/api/v1/json/3/searchevents.php?e=Arsenal_vs_Chelsea
/api/v1/json/3/searchevents.php?e=Arsenal_vs_Chelsea&s=2016-2017

Search for event by event file name
/api/v1/json/3/searchfilename.php?e=English_Premier_League_2015-04-26_Arsenal_vs_Chelsea

Search for Venue
/api/v1/json/3/searchvenues.php?t=Wembley

NOTE: You can replace spaces '%20' with underscores if you want, when requesting multi word strings.

 List

List all sports patreon icon
/api/v1/json/3/all_sports.php

List all leagues (limited 50 on free tier)
/api/v1/json/3/all_leagues.php

List all countries
/api/v1/json/3/all_countries.php

List all Leagues in a country (limited 50 on free tier)
/api/v1/json/3/search_all_leagues.php?c=England
/api/v1/json/3/search_all_leagues.php?c=England&s=Soccer

List all Seasons in a League
/api/v1/json/3/search_all_seasons.php?id=4328

List all Teams in a League
/api/v1/json/3/search_all_teams.php?l=English%20Premier%20League
/api/v1/json/3/search_all_teams.php?s=Soccer&c=Spain

List All teams details in a league by Id patreon icon
/api/v1/json/3/lookup_all_teams.php?id=4328

List All players in a team by Team Id patreon icon
/api/v1/json/3/lookup_all_players.php?id=133604

List all users loved teams and players
/api/v1/json/3/searchloves.php?u=zag

 Lookups

League Details by Id patreon icon
/api/v1/json/3/lookupleague.php?id=4346

Team Details by Id patreon icon
/api/v1/json/3/lookupteam.php?id=133604

Player Details by Id
/api/v1/json/3/lookupplayer.php?id=34145937

Venue Details by Id
/api/v1/json/3/lookupvenue.php?id=16163

Event Details by Id patreon icon
/api/v1/json/3/lookupevent.php?id=441613

Event Statistics by Id patreon icon
/api/v1/json/3/lookupeventstats.php?id=1032723

Event Lineup by Id patreon icon
/api/v1/json/3/lookuplineup.php?id=1032723

List timeline for events by event ID patreon icon
/api/v1/json/3/lookuptimeline.php?id=1032718

Player Honours by Player Id
/api/v1/json/3/lookuphonours.php?id=34147178

Player Milestones by Player Id
/api/v1/json/3/lookupmilestones.php?id=34161397

Player Former Teams by Player Id
/api/v1/json/3/lookupformerteams.php?id=34147178

Player Contracts by Player Id
/api/v1/json/3/lookupcontracts.php?id=34147178

Event Player Results by Event Id
/api/v1/json/3/eventresults.php?id=652890

Event TV by Event Id patreon icon
/api/v1/json/3/lookuptv.php?id=584911

Lookup Table by League ID and Season
/api/v1/json/3/lookuptable.php?l=4328&s=2020-2021 * Featured Soccer Leagues only

Lookup Equipment by Team ID
/api/v1/json/3/lookupequipment.php?id=133597

 Schedules

Next 5 Events by Team Id patreon icon
/api/v1/json/3/eventsnext.php?id=133602

Next 15 Events by League Id patreon icon
/api/v1/json/3/eventsnextleague.php?id=4328

Last 5 Events by Team Id (Limited to home team for free tier)
/api/v1/json/3/eventslast.php?id=133602

Last 15 Events by League Id patreon icon
/api/v1/json/3/eventspastleague.php?id=4328

Events in a specific round by league id/round/season
/api/v1/json/3/eventsround.php?id=4328&r=38&s=2014-2015

Events on a specific day patreon icon
/api/v1/json/3/eventsday.php?d=2014-10-10
/api/v1/json/3/eventsday.php?d=2014-10-10&s=Soccer
/api/v1/json/3/eventsday.php?d=2014-10-10&l=4356
/api/v1/json/3/eventsday.php?d=2014-10-10&l=Australian_A-League

TV Events on a day (By Sport/Date/TV Station Country) patreon icon
/api/v1/json/3/eventstv.php?d=2018-07-07
/api/v1/json/3/eventstv.php?d=2018-07-07&s=Fighting
/api/v1/json/3/eventstv.php?d=2019-09-28&a=United%20Kingdom&s=Cycling
/api/v1/json/3/eventstv.php?c=Peacock_Premium

All events in specific league by season (Free tier limited to 100 events)
/api/v1/json/3/eventsseason.php?id=4328&s=2014-2015

NOTE: These round numbers relate to special strings:
Round 125 = Quarter-Final
Round 150 = Semi-Final
Round 160 = Playoff
Round 170 = Playoff Semi-Final
Round 180 = Playoff Final
Round 200 = Final
Round 500 = Pre-Season

 Images

Preview Images
Most of the time you won't want to download the original large image, just get a small preview.
This is possible simple by adding ''/preview'' onto the end URL. This will give you a small 200px version.
Original - /images/media/league/fanart/xpwsrw1421853005.jpg
Medium 500px - /images/media/league/fanart/xpwsrw1421853005.jpg/medium
Small 250px - /images/media/league/fanart/xpwsrw1421853005.jpg/small
Tiny 50px - /images/media/league/badge/pdd43f1610891709.png/tiny

 Video Highlights patreon icon
Latest Event Youtube Highlights
/api/v1/json/{APIKEY}/eventshighlights.php
/api/v1/json/{APIKEY}/eventshighlights.php?d=2019-10-13
/api/v1/json/{APIKEY}/eventshighlights.php?d=2019-10-12&l=WTA%20Tour
/api/v1/json/{APIKEY}/eventshighlights.php?l=MLB
/api/v1/json/3/eventshighlights.php?i=4329
/api/v1/json/{APIKEY}/eventshighlights.php?s=Soccer
/api/v1/json/{APIKEY}/eventshighlights.php?s=Soccer&d=2020-02-15

 Larger API Limits patreon icon
Show ALL events from season (developer key is limited to 250 events).
/api/v1/json/3/eventsseason.php?id=4424&s=2019

 Livescores V1 patreon icon
NOTE: V2 is now recommended for livescore
These are just a static examples for non-patreon
Soccer - /api/v1/json/3/latestsoccer.php
NCAA Basketball - /api/v1/json/3/latestncaabasketball.php
NCAA Football - /api/v1/json/3/latestncaafootball.php
Basketball - /api/v1/json/3/latestbasketball.php
Am Football - /api/v1/json/3/latestamericanfootball.php
Ice Hockey - /api/v1/json/3/latesticehockey.php
Baseball - /api/v1/json/3/latestbaseball.php
NOTE: Updated LIVE every 2mins for Patreon


seperator bar


V2 API
Authentication
Base URL is = https://www.thesportsdb.com/api/v2/json
Send your API key in the header 'X-API-KEY'
Currently, you need to be a patreon supporter to use v2 of the API. Signup here
We recomend HTTPie or Postman for testing
Example (replace xxxxxx with your api key, found on your profile if you are a paid user):


Livescore V2 patreon icon
/api/v2/json/livescore/Soccer
/api/v2/json/livescore/Basketball
/api/v2/json/livescore/Ice_Hockey
/api/v2/json/livescore/4399
/api/v2/json/livescore/4380
/api/v2/json/livescore/all
example livescore data

Lookups V2 (beta) patreon icon
/api/v2/json/lookup/league/4328
/api/v2/json/lookup/team/133675
/api/v2/json/lookup/team_equipment/133597
/api/v2/json/lookup/player/34172575
/api/v2/json/lookup/player_contracts/34146304
/api/v2/json/lookup/player_honours/34146304
/api/v2/json/lookup/player_milestones/34146304
/api/v2/json/lookup/player_teams/34146304
/api/v2/json/lookup/event/441613
/api/v2/json/lookup/event_lineup/1937584
/api/v2/json/lookup/event_results/652890
/api/v2/json/lookup/event_stats/1937584
/api/v2/json/lookup/event_timeline/1937584
/api/v2/json/lookup/event_tv/584911
/api/v2/json/lookup/event_highlights/2044892
/api/v2/json/lookup/venue/15910

All V2 (beta) patreon icon
/api/v2/json/all/countries
/api/v2/json/all/sports
/api/v2/json/all/leagues

List V2 (beta) patreon icon
/api/v2/json/list/seasons/4328
/api/v2/json/list/seasonposters/4328
/api/v2/json/list/players/133604
/api/v2/json/list/players/Manchester_United
/api/v2/json/list/teams/4328
/api/v2/json/list/teams/English_Premier_League

Search V2 (beta) patreon icon
/api/v2/json/search/league/English_Premier_League
/api/v2/json/search/team/Manchester_United
/api/v2/json/search/player/Harry_Kane
/api/v2/json/search/venue/Wembley
/api/v2/json/search/event/FIFA_World_Cup_2022-12-18_Argentina_vs_France
/api/v2/json/searchalternate/league/PFL

Filter V2 (beta) patreon icon
/api/v2/json/filter/events/4328/2003-2004
/api/v2/json/filter/events/day/2024-09-08
/api/v2/json/filter/tv/day/2024-06-22
/api/v2/json/filter/tv/channel/Sky_Sports_Main_Event
/api/v2/json/filter/tv/country/United_Kingdom
/api/v2/json/filter/tv/sport/Motorsport

Schedule V2 (beta) patreon icon
/api/v2/json/schedule/next/league/4328
/api/v2/json/schedule/previous/league/4328
/api/v2/json/schedule/next/team/133612
/api/v2/json/schedule/previous/team/133612
/api/v2/json/schedule/league/4328/2023-2024
This is the API I'm recieving 
// controllers/playerSearchController.js

const axios = require("axios");
const { getCachedData } = require("../utils/cacheHelper");
const { famousLeagueIds } = require("../config/famousLeagues");

// Base URL for the Free Football API via RapidAPI
const baseURL = "https://free-football-api-data.p.rapidapi.com";

// Retrieve the RapidAPI key from environment variables
const rapidApiKey = process.env.RAPIDAPI_KEY;

if (!rapidApiKey) {
  console.error("ERROR: RAPIDAPI_KEY is not set in environment variables.");
  process.exit(1); // Exit if the API key is missing
}

// Helper function to make API requests
const makeApiRequest = async (endpoint, params = {}) => {
  try {
    const response = await axios.get(`${baseURL}/${endpoint}`, {
      params: params,
      headers: {
        "x-rapidapi-host": "free-football-api-data.p.rapidapi.com",
        "x-rapidapi-key": rapidApiKey,
      },
    });
    return response.data;
  } catch (error) {
    if (error.response) {
      console.error(
        `API Error: ${error.response.status} - ${JSON.stringify(
          error.response.data
        )}`
      );
      throw new Error(
        `API Error: ${error.response.data.message || "Unknown error"}`
      );
    } else if (error.request) {
      console.error("No response received from API");
      throw new Error("No response received from API");
    } else {
      console.error("Error setting up the request:", error.message);
      throw new Error("Error setting up the request");
    }
  }
};

/**
 * Search for players by name within famous leagues.
 */
exports.searchPlayers = async (req, res) => {
  const query = req.query.q;

  if (!query) {
    return res.status(400).json({ error: "Search query 'q' is required" });
  }

  const cacheKey = `playerSearch-${query.toLowerCase()}`;

  const fetchPlayers = async () => {
    try {
      const players = [];

      // Step 1: Iterate through famous leagues
      for (const leagueId of famousLeagueIds) {
        // Step 2: Fetch all teams in the league
        const teamsResponse = await makeApiRequest(
          "football-league-all-teams",
          {
            leagueid: leagueId,
          }
        );

        console.log(
          `Fetched teams for League ID ${leagueId}:`,
          JSON.stringify(teamsResponse, null, 2)
        );

        if (
          !teamsResponse ||
          teamsResponse.status !== "success" ||
          !teamsResponse.response ||
          !Array.isArray(teamsResponse.response.teams)
        ) {
          console.warn(`Invalid teams format for league ID: ${leagueId}`);
          continue; // Skip to the next league
        }

        const teams = teamsResponse.response.teams;

        // Optional: Limit the number of teams per league to manage performance
        const limitedTeams = teams.slice(0, 10); // Adjust as needed

        // Step 3: Fetch players for each team
        const playerPromises = limitedTeams.map((team) =>
          makeApiRequest("football-team-players", { teamid: team.id })
        );

        const playersResponses = await Promise.all(playerPromises);

        // Step 4: Filter players by name
        playersResponses.forEach((playersResponse) => {
          console.log(
            `Fetched players:`,
            JSON.stringify(playersResponse, null, 2)
          );

          if (
            !playersResponse ||
            playersResponse.status !== "success" ||
            !playersResponse.response ||
            !Array.isArray(playersResponse.response.players)
          ) {
            console.warn("Invalid players format in team data.");
            return; // Skip to the next team
          }

          const teamPlayers = playersResponse.response.players;

          const matchingPlayers = teamPlayers.filter((player) =>
            player.name.toLowerCase().includes(query.toLowerCase())
          );

          // Enrich player data with team and league information
          const enrichedPlayers = matchingPlayers.map((player) => ({
            player_id: player.id,
            name: player.name,
            position: player.position || "N/A",
            nationality: player.nationality || "N/A",
            team: team.name,
            league_id: leagueId,
            league_name: getLeagueNameById(leagueId), // Helper to get league name
            photo_url: player.photo || null,
          }));

          players.push(...enrichedPlayers);
        });
      }

      return players;
    } catch (error) {
      console.error("Error fetching players:", error.message);
      throw error;
    }
  };

  try {
    const players = await getCachedData(cacheKey, fetchPlayers, 3600); // Cache for 1 hour
    if (players.length > 0) {
      res.json({ count: players.length, players });
    } else {
      res.status(404).json({ error: "No players found matching the query" });
    }
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
};

/**
 * Helper function to get league name by ID.
 * Replace the object below with actual league names based on your famousLeagueIds.
 */
const leagueIdToNameMap = {
  17: "Premier League",
  8: "La Liga",
  35: "Bundesliga",
  23: "Serie A",
  34: "Ligue 1",
  37: "Eredivisie",
  24: "Primeira Liga",
  21: "Süper Lig",
  7: "Scottish Premiership",
  93: "Major League Soccer",
  // Add more mappings as needed
};

const getLeagueNameById = (leagueId) => {
  return leagueIdToNameMap[leagueId] || "Unknown League";
};

/**
 * Get detailed information about a specific player by ID.
 */
exports.getPlayerDetails = async (req, res) => {
  const playerId = req.params.id;

  if (!playerId) {
    return res.status(400).json({ error: "Player ID is required" });
  }

  const cacheKey = `playerDetails-${playerId}`;

  const fetchPlayerDetails = async () => {
    try {
      const playerDetailsResponse = await makeApiRequest(
        "football-player-detail",
        {
          playerid: playerId,
        }
      );

      console.log(
        "Player Details Response:",
        JSON.stringify(playerDetailsResponse, null, 2)
      );

      // Validate response structure
      if (
        !playerDetailsResponse ||
        playerDetailsResponse.status !== "success" ||
        !playerDetailsResponse.response ||
        typeof playerDetailsResponse.response !== "object"
      ) {
        throw new Error("Invalid response format for player details");
      }

      const player = playerDetailsResponse.response;

      // Optionally, fetch media/content
      const mediaResponse = await makeApiRequest("football-player-media", {
        playerid: playerId,
      });

      console.log(
        "Player Media Response:",
        JSON.stringify(mediaResponse, null, 2)
      );

      const media = mediaResponse.response || [];

      return {
        ...player,
        media: media,
      };
    } catch (error) {
      console.error("Error fetching player details:", error.message);
      throw error;
    }
  };

  try {
    const playerDetails = await getCachedData(
      cacheKey,
      fetchPlayerDetails,
      3600
    ); // Cache for 1 hour
    if (playerDetails) {
      res.json({ status: "success", response: playerDetails });
    } else {
      res.status(404).json({ error: "Player not found" });
    }
  } catch (error) {
    if (error.message.includes("404") || error.message.includes("not found")) {
      res.status(404).json({ error: "Player not found" });
    } else {
      res.status(500).json({ error: error.message });
    }
  }
};

/**
 * Get recent matches/events for a specific player.
 */
exports.getPlayerMatches = async (req, res) => {
  const playerId = req.params.id;
  const limit = parseInt(req.query.limit) || 5;

  if (!playerId) {
    return res.status(400).json({ error: "Player ID is required" });
  }

  const cacheKey = `playerMatches-${playerId}-${limit}`;

  const fetchPlayerMatches = async () => {
    try {
      const matchesResponse = await makeApiRequest("football-player-content", {
        playerid: playerId,
      });

      console.log(
        "Player Matches Response:",
        JSON.stringify(matchesResponse, null, 2)
      );

      // Validate response structure
      if (
        !matchesResponse ||
        matchesResponse.status !== "success" ||
        !matchesResponse.response ||
        !Array.isArray(matchesResponse.response.events)
      ) {
        throw new Error("Invalid match data structure");
      }

      const matches = matchesResponse.response.events;

      // Return the most recent 'limit' matches
      const recentMatches = matches.slice(0, limit);

      return recentMatches;
    } catch (error) {
      console.error("Error fetching player matches:", error.message);
      throw error;
    }
  };

  try {
    const playerMatches = await getCachedData(
      cacheKey,
      fetchPlayerMatches,
      3600
    ); // Cache for 1 hour
    if (playerMatches && playerMatches.length > 0) {
      res.json({ count: playerMatches.length, matches: playerMatches });
    } else {
      res
        .status(404)
        .json({ error: "No recent matches found for this player" });
    }
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
};

This is was the previous controller 
now change this controller with API provided now and it has key 3 
Can you do that?? 
I think one thing gonna change I'll able to search directly 
And I need 4-5 players card which you'll send to front-end 
like messi, yamal, neymar, ronaldo, mbbape
make me this controller 
returning all the things