ESPN API: Free Sports Data for Scores, Stats & News
Access ESPN's hidden API endpoints for comprehensive sports data - no API key required
What is the ESPN API?
The ESPN API refers to a collection of undocumented endpoints that developers have discovered by reverse-engineering ESPN's web and mobile applications. While ESPN doesn't offer an official public API, these hidden endpoints provide free access to a wealth of sports data:
- Real-time Scores: Live scoreboards across all major sports
- Team & Player Stats: Comprehensive statistics and performance data
- News & Headlines: Latest sports news articles
- Standings & Rankings: League standings and power rankings
- Game Summaries: Play-by-play data, box scores, and game details
- Schedules: Upcoming games and event calendars
Key Benefits
- Free Access: No subscription or payment required
- No Authentication: No API key or token needed
- JSON Responses: Clean, structured data format
- Comprehensive Coverage: All major US sports plus international soccer
API Base URLs
ESPN's hidden API uses several base domains, each serving different types of data:
| Domain | Purpose |
|---|---|
site.api.espn.com |
General site data - scores, news, teams, standings |
sports.core.api.espn.com |
Core sports data - athletes, detailed stats, odds, venues |
site.web.api.espn.com |
Web-specific APIs - search, game summaries, athlete overviews |
fantasy.espn.com |
Fantasy sports data (may require authentication for private leagues) |
cdn.espn.com |
Content delivery - optimized for speed and caching |
Supported Sports & Leagues
The ESPN API covers a wide range of sports and leagues. Here are the most commonly used:
Football
- NFL (
football/nfl) - College Football (
football/college-football)
Basketball
- NBA (
basketball/nba) - WNBA (
basketball/wnba) - Men's CBB (
basketball/mens-college-basketball) - Women's CBB (
basketball/womens-college-basketball)
Baseball
- MLB (
baseball/mlb) - College Baseball (
baseball/college-baseball)
Hockey
- NHL (
hockey/nhl)
Soccer
- MLS (
soccer/usa.1) - Premier League (
soccer/eng.1) - La Liga (
soccer/esp.1) - And many more...
Other Sports
- Golf
- Tennis
- MMA/UFC
- Racing
Key Endpoints
Most endpoints follow a consistent pattern: /apis/site/v2/sports/{sport}/{league}/{endpoint}
| Endpoint | Description | Example |
|---|---|---|
/scoreboard |
Live scores and game status | /sports/football/nfl/scoreboard |
/news |
Latest news articles | /sports/basketball/nba/news |
/teams |
All teams in a league | /sports/baseball/mlb/teams |
/teams/{id} |
Specific team details | /sports/football/nfl/teams/12 |
/summary |
Game details with box score | /sports/basketball/nba/summary?event=401234567 |
/standings |
League standings | /sports/hockey/nhl/standings |
/rankings |
Power rankings (college) | /sports/football/college-football/rankings |
Common Query Parameters
| Parameter | Description | Example |
|---|---|---|
dates |
One day (YYYYMMDD) or a whole month (YYYYMM). Ranges return HTTP 400, see date filters | ?dates=20251201 |
limit |
Maximum number of results | ?limit=50 |
season |
Specific season year | ?season=2025 |
seasontype |
Season type (1=preseason, 2=regular, 3=postseason) | ?seasontype=2 |
week |
Specific week (football) | ?week=10 |
groups |
Conference/division filter | ?groups=80 (FBS) |
ESPN Game Summary Endpoint (summary?event=)
The summary endpoint returns everything ESPN has on one game: box score, play-by-play, win probability, betting lines, injuries and news. It is the ESPN endpoint developers search for most, and it has the least documentation.
https://site.api.espn.com/apis/site/v2/sports/{sport}/{league}/summary?event={eventId}
https://site.web.api.espn.com/apis/site/v2/sports/{sport}/{league}/summary?event={eventId}
Both hosts returned the same JSON for the same game in our tests. Pick either one.
Where the event ID comes from
Every scoreboard response has an events array, and each event has an id. That id is your event value. For example, basketball/nba/scoreboard?dates=20250605 returns Game 1 of the 2025 NBA Finals (Pacers at Thunder) with id 401766122, so the summary URL is basketball/nba/summary?event=401766122. A missing or wrong ID returns HTTP 400.
What the summary response contains
| Key | What it holds |
|---|---|
header |
Teams, score, date, status and which side is home |
boxscore |
Team stats (teams) and player stat lines (players) |
plays |
Play-by-play. Our NBA Finals test game had 503 plays, each with an id, text, period and clock |
winprobability |
Home win probability after every play (see below) |
leaders |
Top performer per stat category for each team |
odds, pickcenter, againstTheSpread |
Betting lines and against-the-spread records. Often empty for finished games: both were empty for our NBA test game |
injuries |
Injury report for both teams |
gameInfo |
Venue, attendance and officials |
standings, seasonseries |
League table and the season head-to-head |
news, article, videos |
Recap and highlight content |
Other sports use the same path with their own sport and league. Football responses add drives and scoringPlays. Soccer responses add keyEvents (a match timeline), commentary and rosters. A 2026 World Cup match looks like soccer/fifa.world/summary?event=760506 (Portugal vs Spain).
ESPN Win Probability Data
ESPN publishes a win probability for every play, and there are two ways to get it. Use the summary endpoint unless you have a reason not to.
From the summary endpoint
The winprobability array has one row per play:
{"homeWinPercentage": 0.665, "tiePercentage": 0.0, "playId": "4017661224"}
Values are fractions, not percents. The away side's chance is 1 - homeWinPercentage - tiePercentage. To see which play moved the number, match playId to the id of an entry in plays:
import requests
event_id = '401766122' # 2025 NBA Finals, Game 1
url = f'https://site.api.espn.com/apis/site/v2/sports/basketball/nba/summary?event={event_id}'
data = requests.get(url).json()
plays = {p['id']: p for p in data['plays']}
for row in data['winprobability'][-5:]:
play = plays.get(row['playId'], {})
clock = play.get('clock', {}).get('displayValue', '')
print(f"{row['homeWinPercentage']:.1%} Q{play.get('period', {}).get('number')} {clock} {play.get('text', '')}")
From the core API
https://sports.core.api.espn.com/v2/sports/basketball/leagues/nba/events/{eventId}/competitions/{eventId}/probabilities
For NBA games the competition ID is the same as the event ID. This version is paginated (?limit= and ?page=) and each item is a $ref link, so every play costs one more request. The records do carry extra fields: awayWinPercentage, spreadCoverProbHome and totalOverProb. The spread and total fields were all 0 in our test, so the summary array gives you the same useful numbers in one call.
ESPN Scoreboard URLs by League
Every URL below returned HTTP 200 when we tested it. With no dates parameter you get today's games, or the current week for football.
| League | Scoreboard URL |
|---|---|
| NBA | https://site.api.espn.com/apis/site/v2/sports/basketball/nba/scoreboard |
| NFL | https://site.api.espn.com/apis/site/v2/sports/football/nfl/scoreboard |
| College football | https://site.api.espn.com/apis/site/v2/sports/football/college-football/scoreboard |
| MLB | https://site.api.espn.com/apis/site/v2/sports/baseball/mlb/scoreboard |
| NHL | https://site.api.espn.com/apis/site/v2/sports/hockey/nhl/scoreboard |
| Premier League | https://site.api.espn.com/apis/site/v2/sports/soccer/eng.1/scoreboard |
| La Liga | https://site.api.espn.com/apis/site/v2/sports/soccer/esp.1/scoreboard |
| FIFA World Cup | https://site.api.espn.com/apis/site/v2/sports/soccer/fifa.world/scoreboard |
| Every soccer league | https://site.api.espn.com/apis/site/v2/sports/soccer/all/scoreboard |
| PGA Tour | https://site.api.espn.com/apis/site/v2/sports/golf/pga/scoreboard |
Cricket is the odd one out. It takes a numeric league ID in place of a slug: cricket/8048/scoreboard returned a match, while cricket/scoreboard returned 404.
Date filters
| Format | Example | What we got back |
|---|---|---|
| YYYYMMDD | basketball/nba/scoreboard?dates=20250605 |
One day: Game 1 of the 2025 NBA Finals |
| YYYYMM | basketball/nba/scoreboard?dates=202506 |
A whole month: all 7 games of the 2025 NBA Finals |
| YYYYMM | soccer/fifa.world/scoreboard?dates=202606 |
79 World Cup matches from June 2026 |
| Season + week | football/nfl/scoreboard?dates=2025&seasontype=2&week=1 |
Week 1 of the 2025 NFL regular season (16 games) |
| YYYYMMDD-YYYYMMDD | basketball/nba/scoreboard?dates=20250601-20250630 |
HTTP 400. Ranges failed for every league we tried |
Need a range? Request it month by month and filter the dates yourself.
Code Examples
Here are practical examples for fetching data from the ESPN API:
Get NFL Scores
// Fetch today's NFL scores
fetch('https://site.api.espn.com/apis/site/v2/sports/football/nfl/scoreboard')
.then(response => response.json())
.then(data => {
data.events.forEach(game => {
console.log(game.name, game.status.type.description);
});
});
import requests
# Fetch today's NFL scores
url = 'https://site.api.espn.com/apis/site/v2/sports/football/nfl/scoreboard'
response = requests.get(url)
data = response.json()
for game in data['events']:
print(game['name'], game['status']['type']['description'])
# Fetch today's NFL scores curl 'https://site.api.espn.com/apis/site/v2/sports/football/nfl/scoreboard'
Get NBA Game Summary
// Fetch detailed game data (replace eventId with actual game ID)
const eventId = '401584793';
const url = `https://site.web.api.espn.com/apis/site/v2/sports/basketball/nba/summary?event=${eventId}`;
fetch(url)
.then(response => response.json())
.then(data => {
console.log('Boxscore:', data.boxscore);
console.log('Play-by-play:', data.plays);
});
import requests
# Fetch detailed game data
event_id = '401584793'
url = f'https://site.web.api.espn.com/apis/site/v2/sports/basketball/nba/summary?event={event_id}'
response = requests.get(url)
data = response.json()
print('Boxscore:', data.get('boxscore'))
print('Play-by-play:', data.get('plays'))
Get Scores for Specific Date
// Fetch MLB scores for a specific date
const date = '20251001'; // YYYYMMDD format
fetch(`https://site.api.espn.com/apis/site/v2/sports/baseball/mlb/scoreboard?dates=${date}`)
.then(response => response.json())
.then(data => console.log(data));
ESPN API 403 and 400 Errors
403 Forbidden
ESPN serves these endpoints through a CDN that blocks some scripted traffic. In our tests, a script that sent a copied Chrome User-Agent header got 403 on every request. The same URLs returned 200 with the default headers of curl, Python requests and Node fetch. If your script sets a browser User-Agent, delete that header first.
If the 403 continues after that, slow down and cache what you fetch. ESPN publishes no rate limit, so there is no safe number to aim for.
400 Bad Request
- No valid event ID:
summaryneeds?event=with an id from a scoreboard response - A date range:
?dates=20250601-20250630fails. Use one day or one month
200 with an empty events array
That means no games on that date, not a broken endpoint. Try a date you know had games.
Limitations & Considerations
Important: Unofficial API
The ESPN API is not officially supported. Keep these limitations in mind:
- No Official Documentation: These endpoints are undocumented and discovered through reverse engineering
- No Stability Guarantee: ESPN can modify or remove endpoints at any time without notice
- Unknown Rate Limits: There's no published information about rate limiting or usage quotas
- No Support: ESPN does not provide developer support for these endpoints
- Terms of Service: Heavy automated usage may violate ESPN's terms of service
Recommendations
- For Hobby Projects: The ESPN API works great for personal projects, learning, and experimentation
- For Production Apps: Consider official sports data providers for applications requiring guaranteed uptime and support
- Error Handling: Implement robust error handling since endpoints may change unexpectedly
- Caching: Cache responses to reduce API calls and improve reliability
Community Resources
These community-maintained resources provide additional documentation and tools for working with the ESPN API:
ESPN API GitHub Repository
Comprehensive community documentation with endpoint references and examples
ESPN Hidden API Gist
Original endpoint discovery documentation with URL patterns for multiple sports
ESPN API Tutorial
Step-by-step guide on accessing ESPN's free sports data endpoints
ESPN Hidden API Guide
Getting started guide with best practices and common use cases
GPWA Forum Discussion
Community forum thread with additional endpoint discoveries and tips
Frequently Asked Questions
https://site.api.espn.com/apis/site/v2/sports/basketball/nba/scoreboard. The response includes all games for the current day with scores, team info, and game status. Add ?dates=YYYYMMDD to get scores for a specific date.site.web.api.espn.com also serves some web-only data, such as search and athlete overviews.https://site.api.espn.com/apis/site/v2/sports/basketball/nba/summary?event=401766122, and read the winprobability array. Each row has homeWinPercentage, tiePercentage and a playId that matches a play in the plays array. Full example above.User-Agent header. Remove that header and let your HTTP client send its default. The same requests then returned 200. More on 403 and 400 errors.Need More Reliable Sports Data?
While the ESPN API is great for hobby projects, production applications often need guaranteed uptime and official support. Compare professional sports data providers in our directory.