# ESPN Scraper — Scores, Box Scores, Play-by-Play & Odds (`logiover/espn-scraper`) Actor

Scrape ESPN for NFL, NBA, MLB, NHL, college, soccer, tennis, UFC and golf: games and results with betting lines, player and team box scores, play-by-play, standings, rosters, injuries and career game logs. Whole seasons in minutes, no API key. Not affiliated with ESPN.

- **URL**: https://apify.com/logiover/espn-scraper.md
- **Developed by:** [Logiover](https://apify.com/logiover) (community)
- **Categories:** News, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## ESPN Scraper — Scores, Box Scores, Play-by-Play, Odds & Stats

**ESPN Scraper** pulls ESPN sports data into clean, flat tables: **games and scores with betting lines, player box scores, team box scores, play-by-play, standings, teams, rosters, injury reports and player career game logs** for the **NFL, NBA, MLB, NHL, WNBA, college football and college basketball, MLS, the Premier League, LALIGA, Bundesliga, Serie A, Ligue 1, the Champions League, ATP and WTA tennis, UFC, PGA golf and Formula 1**. Ask for a whole season or any date range and get every game — a full NBA season of player box scores (**28,704 rows**) in under a minute, a full NFL season of play-by-play (**51,601 plays**) in 46 seconds.

It is an **ESPN API alternative** that needs **no API key, no login and no coding**: it reads the same public JSON that espn.com and the ESPN app use, so numbers match what you see on ESPN. Export to **CSV, Excel, JSON or XML**, call it from the **Apify API** (Python, Node.js, curl), or plug it into **Google Sheets, Make, Zapier, n8n** and AI agents through **MCP**. Built for sports-betting models, fantasy sports tools, sports media and newsrooms, data science courses and anyone who needs ESPN stats in bulk without copy-pasting box scores.

> **Independent tool.** ESPN Scraper is not affiliated with, endorsed by or sponsored by ESPN, Inc. or The Walt Disney Company. ESPN is a trademark of its owner. The Actor only reads publicly available pages and data.

***

### What you can scrape

| Mode | One row per | Main fields | Typical volume |
|---|---|---|---|
| **Games & scores** | game (or tennis match / UFC bout / golf tournament) | date, teams, score, score by period, records, winner, venue, attendance, TV, **spread, total, moneylines (as shown on ESPN)**, status | NBA season ≈ 1,330 games · NCAA men's basketball season ≈ 4,800 games · ATP + WTA year ≈ 12,400 matches |
| **Player box scores** | player per game (per stat table) | minutes, points, rebounds, assists, shooting splits, +/-, passing/rushing/receiving/defense, batting/pitching, skater/goalie lines, soccer goals/shots/cards | NBA season ≈ 28,700 · Big-5 soccer season ≈ 54,300 |
| **Team box scores** | team per game | every team stat ESPN shows (FG%, turnovers, fast-break points, third-down efficiency, possession, batting/pitching/fielding…) | NBA season ≈ 2,650 |
| **Play-by-play** | play | period, clock, team, play type, description, score after the play, players involved, shot/ice coordinates, **down & distance & yard line (football)**, **pitch type & velocity & count (baseball)**, soccer minute-by-minute commentary | NFL season ≈ 51,600 · NBA game ≈ 450 |
| **Standings** | team | rank, W-L-T, win %, games behind, streak, home/away/division/conference records, points for/against, playoff seed, clinch flag, qualification note | any season back to the 2000s |
| **Teams** | team | name, abbreviation, colors, logo, record, standing summary, home venue, next game, ESPN links | 30 NBA teams · 362 Division I basketball teams |
| **Rosters** | player | jersey, position, age, birth date, height, weight, experience, college, birthplace, status, injury status, **salary (NBA/NFL where ESPN lists it)**, head coach | NFL + NBA ≈ 3,200 players |
| **Injury reports** | injured player | status (Out, Questionable, IR…), injury, body part, expected return date, latest news blurb | NFL + NBA + NHL + MLB ≈ 1,350 |
| **Player game logs** | player per game | every game of a player's career with the full stat line | LeBron James career ≈ 1,900 games |

Every row carries `league`, `season`, `gameId` / `teamId` / `athleteId` so you can join modes (box scores ↔ games ↔ plays ↔ rosters).

### Supported leagues

- **American football:** NFL, NCAA Football (FBS and FCS), UFL
- **Basketball:** NBA, WNBA, NCAA Men's and Women's Basketball (all Division I games), NBA G League
- **Baseball:** MLB, NCAA Baseball, World Baseball Classic
- **Hockey:** NHL, NCAA Men's Hockey
- **Soccer:** Premier League, Championship, FA Cup, Carabao Cup, LALIGA, Bundesliga, Serie A, Ligue 1, Eredivisie, Primeira Liga, Scottish Premiership, Belgian Pro League, Turkish Süper Lig, Saudi Pro League, MLS, NWSL, Liga MX, Brazilian Série A, Argentine Liga Profesional, J1 League, A-League, UEFA Champions League, Europa League, Conference League, Copa Libertadores, Concacaf Champions Cup, FIFA World Cup, EURO, FIFA Club World Cup — **plus any other ESPN league** by its ESPN code (e.g. `soccer/ger.2`, `soccer/esp.2`) in *Other ESPN leagues*
- **Tennis:** ATP and WTA tours (every draw of every tournament, singles and doubles, with set scores and tiebreaks)
- **Combat sports:** UFC (every bout with weight class, records, winner, round and time)
- **Golf & motor sport:** PGA Tour, LPGA (leaderboards with round scores), Formula 1 (session classifications)
- **Other:** Premier Lacrosse League, AFL

### Who uses it

- **Sports betting and prediction models** — years of results, closing lines and player stats in one table; refresh daily for upcoming games with spreads, totals and moneylines.
- **Fantasy sports** — player game logs, box scores, injury reports and rosters for projections and lineup tools.
- **Media, newsrooms and creators** — standings, leaders and recaps for articles, graphics and social posts.
- **Data science and teaching** — clean, joinable datasets for regression, Elo/rating models, expected-goals work and dashboards.
- **AI and LLM apps** — feed agents and RAG pipelines with fresh, structured sports facts through the Apify API or MCP.
- **Clubs, agencies and scouts** — per-player match stats across many leagues and seasons.

### How to use ESPN Scraper

1. Click **Try for free** (or **Start**) and pick **What to scrape** — e.g. *Player box scores*.
2. Choose one or more **Leagues** and enter **Seasons** (e.g. `2025-26`) or a **date range**.
3. Set **Max rows** (0 = everything) and press **Start**. Rows stream into the **Output** tab in date order; export CSV, Excel or JSON when the run finishes.

Seasons accept `2025-26` for every league: it means the 2025-26 NBA/NHL/college-basketball season, the 2025 NFL/MLB/WNBA/MLS season and the 2025-26 European soccer season. You can also use ESPN's own season year (NBA `2026` = 2025-26, NFL `2025`, Premier League `2025` = 2025-26).

### Input examples

**Every game of the 2025-26 NBA season with scores, records and TV:**

```json
{ "mode": "games", "leagues": ["nba"], "seasons": ["2025-26"], "maxItems": 0 }
```

**This week's NFL schedule with DraftKings lines, referees and weather:**

```json
{ "mode": "games", "leagues": ["nfl"], "dateFrom": "today", "dateTo": "+7 days", "includeGameDetails": true }
```

**All player box scores of a season (regular season + playoffs):**

```json
{ "mode": "playerStats", "leagues": ["nba"], "seasons": ["2025-26"], "seasonType": "regular+postseason", "maxItems": 0 }
```

**Player match stats for Europe's top five soccer leagues:**

```json
{ "mode": "playerStats", "leagues": ["eng.1", "esp.1", "ger.1", "ita.1", "fra.1"], "seasons": ["2024-25"], "maxItems": 0 }
```

**Play-by-play of one team's games:**

```json
{ "mode": "plays", "leagues": ["nfl"], "seasons": ["2025"], "teams": ["KC"], "maxItems": 0 }
```

**Specific games by URL (box score of each):**

```json
{ "mode": "playerStats", "gameIds": ["https://www.espn.com/nba/game/_/gameId/401809243/rockets-thunder"] }
```

**Standings of several leagues and seasons:**

```json
{ "mode": "standings", "leagues": ["nba", "nfl", "eng.1"], "seasons": ["2023-24", "2024-25"] }
```

**Current rosters (with salaries where ESPN lists them) and injury report:**

```json
{ "mode": "rosters", "leagues": ["nfl", "nba"], "maxItems": 0 }
```

```json
{ "mode": "injuries", "leagues": ["nfl", "nba", "nhl", "mlb"] }
```

**Whole-career game logs of players (by name or ESPN URL):**

```json
{ "mode": "playerGameLogs", "athletes": ["LeBron James", "https://www.espn.com/nfl/player/_/id/3139477/patrick-mahomes"] }
```

**Every ATP and WTA match of a year:**

```json
{ "mode": "games", "leagues": ["atp", "wta"], "seasons": ["2025"], "onlyCompleted": true, "maxItems": 0 }
```

### Input reference

| Field | What it does |
|---|---|
| `mode` | `games`, `playerStats`, `teamStats`, `plays`, `standings`, `teams`, `rosters`, `injuries` or `playerGameLogs` |
| `leagues` | One or more league keys from the list (`nfl`, `nba`, `mlb`, `nhl`, `wnba`, `college-football`, `mens-college-basketball`, `eng.1`, `esp.1`, `uefa.champions`, `atp`, `ufc`, `pga`, `f1` …) |
| `customLeagues` | Any other ESPN league as `sport/code` (`soccer/ger.2`) or an ESPN league URL |
| `seasons` | Whole seasons: `2025-26`, `2024-25`, or ESPN season years like `2026` |
| `seasonType` | `auto` (default: regular season + playoffs for whole seasons, every game for date ranges), `regular+postseason`, `regular`, `postseason` (incl. NBA play-in), `preseason`, `all` |
| `dateFrom` / `dateTo` | Date range instead of seasons: `2025-12-25`, `7 days` (ago), `yesterday`, `today`, `+7 days` (ahead) |
| `teams` | Keep only these teams: abbreviation (`LAL`), name (`Lakers`, `Boston Celtics`) or ESPN team ID |
| `onlyCompleted` | Games mode: drop scheduled and live games |
| `gameIds` | Exact games as ESPN URLs or IDs (games, box scores and play-by-play) |
| `athletes` | Players for game logs: names, ESPN player URLs or IDs |
| `includeDidNotPlay` | Player box scores: add rows for DNP / inactive / unused substitutes with the reason |
| `includeGameDetails` | Games mode: add officials, closing betting lines, weather and venue capacity (1 extra request per game) |
| `includeTeamDetails` | Teams mode: add record, standing summary, venue and next game (default on) |
| `maxItems` | Stop after this many rows (0 = no limit) |
| `concurrency` | Parallel requests (default 24) |
| `proxyConfiguration` | Fallback proxy; ESPN is read directly and the proxy is only used if ESPN starts refusing requests |

If you leave seasons and dates empty, games mode returns the last 3 days and the next 7 days (results + upcoming schedule with lines), and the box-score modes return the last 7 days.

### Output examples (real rows from test runs on 2026-10-15)

**Games & scores** — NBA opening night 2025-26:

```json
{
  "league": "NBA",
  "leagueKey": "nba",
  "sport": "basketball",
  "season": 2026,
  "seasonType": "Regular Season",
  "week": null,
  "gameId": "401809243",
  "date": "2025-10-21T23:30:00.000Z",
  "name": "Houston Rockets at Oklahoma City Thunder",
  "shortName": "HOU @ OKC",
  "status": "Final",
  "statusDetail": "Final/2OT",
  "state": "post",
  "completed": true,
  "homeTeamId": "25",
  "homeTeam": "Oklahoma City Thunder",
  "homeTeamAbbreviation": "OKC",
  "homeScore": 125,
  "homeWinner": true,
  "homeRecord": "1-0",
  "homeLinescores": "27|24|24|29|11|10",
  "awayTeamId": "10",
  "awayTeam": "Houston Rockets",
  "awayTeamAbbreviation": "HOU",
  "awayScore": 124,
  "awayWinner": false,
  "awayRecord": "0-1",
  "awayLinescores": "30|27|22|25|11|9",
  "winner": "OKC",
  "margin": 1,
  "totalScore": 249,
  "periods": 6,
  "overtime": true,
  "venue": "Paycom Center",
  "venueCity": "Oklahoma City",
  "venueState": "OK",
  "venueCountry": null,
  "attendance": 18203,
  "neutralSite": false,
  "conferenceGame": false,
  "broadcasts": "NBC | Peacock",
  "notes": null,
  "headline": "Thunder celebrate ring ceremony, banner unveiling and double-OT win over Durant's Rockets",
  "gameUrl": "https://www.espn.com/nba/game/_/gameId/401809243/rockets-thunder",
  "scrapedAt": "2026-10-15T09:40:59.025Z"
}
```

**Games with betting lines and weather** (`includeGameDetails: true`) — the odds part of an upcoming NFL game:

```json
{
  "league": "NFL",
  "week": 6,
  "gameId": "401872995",
  "date": "2026-10-16T00:15:00.000Z",
  "shortName": "SEA @ DEN",
  "status": "Scheduled",
  "oddsProvider": "DraftKings",
  "oddsDetails": "SEA -2.5",
  "homeSpread": 2.5,
  "overUnder": 40.5,
  "homeMoneyline": 120,
  "awayMoneyline": -142,
  "homeSpreadOdds": -108,
  "awaySpreadOdds": -112,
  "overOdds": -112,
  "underOdds": -108,
  "favoriteSide": "away",
  "homeMoneylineOpen": 110,
  "awayMoneylineOpen": -130,
  "homeSpreadOpen": 2.5,
  "overUnderOpen": 43.5,
  "weather": "Mostly sunny",
  "temperatureF": 54,
  "windGustMph": 8,
  "precipitationChancePct": 20,
  "grass": true
}
```

**Player box score** — one NBA player line:

```json
{
  "league": "NBA",
  "leagueKey": "nba",
  "sport": "basketball",
  "season": 2026,
  "seasonType": "Regular Season",
  "week": null,
  "gameId": "401809243",
  "gameDate": "2025-10-21T23:30:00.000Z",
  "teamId": "10",
  "team": "Houston Rockets",
  "teamAbbreviation": "HOU",
  "homeAway": "away",
  "opponentId": "25",
  "opponent": "Oklahoma City Thunder",
  "opponentAbbreviation": "OKC",
  "teamScore": 124,
  "opponentScore": 125,
  "result": "L",
  "athleteId": "3202",
  "athleteName": "Kevin Durant",
  "jersey": "7",
  "position": "F",
  "starter": true,
  "didNotPlay": false,
  "dnpReason": null,
  "ejected": false,
  "statGroup": null,
  "minutes": 47,
  "points": 23,
  "fieldGoalsMade": 9,
  "fieldGoalsAttempted": 16,
  "threePointFieldGoalsMade": 0,
  "threePointFieldGoalsAttempted": 4,
  "freeThrowsMade": 5,
  "freeThrowsAttempted": 6,
  "rebounds": 9,
  "assists": 3,
  "turnovers": 4,
  "steals": 0,
  "blocks": 0,
  "offensiveRebounds": 0,
  "defensiveRebounds": 9,
  "fouls": 6,
  "plusMinus": 0,
  "athleteUrl": "https://www.espn.com/nba/player/_/id/3202/kevin-durant",
  "gameUrl": "https://www.espn.com/nba/game/_/gameId/401809243/rockets-thunder",
  "scrapedAt": "2026-10-15T09:41:35.979Z"
}
```

**Player box score (soccer)** — Premier League, same mode:

```json
{
  "league": "English Premier League",
  "season": 2024,
  "gameId": "704397",
  "gameDate": "2024-11-24T14:00:00.000Z",
  "team": "Liverpool",
  "opponent": "Southampton",
  "result": "W",
  "teamScore": 3,
  "opponentScore": 2,
  "athleteName": "Mohamed Salah",
  "position": "AM-R",
  "positionName": "Attacking Midfielder Right",
  "starter": true,
  "subbedIn": false,
  "subbedOut": false,
  "totalGoals": 2,
  "goalAssists": 0,
  "totalShots": 7,
  "shotsOnTarget": 4,
  "foulsCommitted": 1,
  "foulsSuffered": 2,
  "yellowCards": 1,
  "redCards": 0,
  "offsides": 0,
  "athleteUrl": "https://www.espn.com/soccer/player/_/id/173896/mohamed-salah"
}
```

**Play-by-play (football)** — down, distance, yard line and drive context on every play:

```json
{
  "league": "NFL",
  "leagueKey": "nfl",
  "sport": "football",
  "season": 2025,
  "seasonType": "Regular Season",
  "gameId": "401772714",
  "gameDate": "2025-09-06T00:00:00.000Z",
  "homeTeam": "LAC",
  "awayTeam": "KC",
  "playId": "4017727141132",
  "sequence": 113200,
  "period": 2,
  "clock": "13:47",
  "driveNumber": 6,
  "driveId": "4017727146",
  "driveTeam": "LAC",
  "driveResult": "Field Goal",
  "driveDescription": "9 plays, 58 yards, 4:40",
  "offenseTeam": "LAC",
  "defenseTeam": "KC",
  "type": "Field Goal Good",
  "typeId": "59",
  "text": "C.Dicker 39 yard field goal is GOOD, Center-R.Lovato, Holder-J.Scott.Penalty on KC-J.Williams, Defensive Offside, declined.",
  "down": 4,
  "distance": 16,
  "yardLine": 79,
  "yardsToEndzone": 21,
  "possessionText": "KC 21",
  "yardsGained": 39,
  "endDown": null,
  "endDistance": 10,
  "endYardsToEndzone": 0,
  "scoringPlay": true,
  "isPenalty": false,
  "isTurnover": false,
  "homeScore": 10,
  "awayScore": 0,
  "wallclock": "2025-09-06T00:52:00.000Z",
  "scrapedAt": "2026-10-15T09:53:11.335Z"
}
```

**Standings:**

```json
{
  "league": "NBA",
  "seasonName": "2024-25",
  "seasonType": "Regular Season",
  "group": "Eastern Conference",
  "subgroup": "Atlantic",
  "rank": 1,
  "team": "Boston Celtics",
  "wins": 61,
  "losses": 21,
  "winPercent": 0.7439,
  "gamesBehind": 0,
  "playoffSeed": 2,
  "clincher": "y",
  "streak": "W2",
  "pointsFor": 9534,
  "pointsAgainst": 8787,
  "overallRecord": "61-21",
  "homeRecord": "28-13",
  "awayRecord": "33-8",
  "divisionRecord": "14-2",
  "conferenceRecord": "39-13",
  "lastTenRecord": "8-2"
}
```

**Tennis match** (games mode with `atp` / `wta`):

```json
{
  "league": "ATP Tour (tennis)",
  "event": "Brisbane International presented by ANZ",
  "major": false,
  "gameId": "152644",
  "date": "2024-12-28T01:00:00.000Z",
  "draw": "Men's Singles",
  "round": "Qualifying 1st Round",
  "player1": "Derek Pham",
  "player1Country": "Australia",
  "player1Seed": null,
  "player1Sets": "1|2",
  "player2": "Richard Gasquet",
  "player2Country": "France",
  "player2Sets": "6|6",
  "winner": "Richard Gasquet",
  "score": "6-1 6-2",
  "result": "Richard Gasquet (FRA) bt Derek Pham (AUS) 6-1 6-2",
  "court": "Show Court 2"
}
```

**Roster player:**

```json
{
  "league": "NFL",
  "team": "New England Patriots",
  "athleteName": "Christian Elliss",
  "jersey": "53",
  "position": "LB",
  "positionGroup": "defense",
  "age": 27,
  "dateOfBirth": "1999-01-02",
  "height": "6' 2\"",
  "weightLbs": 231,
  "experienceYears": 5,
  "college": "Idaho",
  "birthCity": "Highlands Ranch",
  "status": "Active",
  "injuryStatus": "Questionable",
  "salary": 7379000,
  "headCoach": "Mike Vrabel",
  "athleteUrl": "https://www.espn.com/nfl/player/_/id/4245273/christian-elliss"
}
```

**Player game log** (one game of a career):

```json
{
  "league": "NBA",
  "seasonType": "2026-27 Preseason",
  "athleteName": "LeBron James",
  "gameId": "401901823",
  "gameDate": "2026-10-08T23:30:00.000Z",
  "team": "PHI",
  "homeAway": "away",
  "opponent": "Brooklyn Nets",
  "result": "L",
  "teamScore": 108,
  "opponentScore": 114,
  "minutes": 18,
  "points": 10,
  "totalRebounds": 4,
  "assists": 5,
  "fieldGoalsMade": 1,
  "fieldGoalsAttempted": 1
}
```

### Data dictionary

**Fields on every row:** `league` (display name), `leagueKey` (`nba`, `eng.1` …), `sport`, `scrapedAt` (UTC). Game-based rows add `season` (ESPN season year), `seasonType` (Preseason / Regular Season / Postseason / Play-In, or the cup stage for soccer competitions) and `week` (football only).

**Games** — `gameId`, `date` (UTC kick-off), `name`, `shortName`, `status`, `statusDetail` (e.g. `Final/2OT`), `state` (`pre` / `in` / `post`), `completed`; `homeTeamId`, `homeTeam`, `homeTeamAbbreviation`, `homeScore`, `homeWinner`, `homeRecord`, `homeLinescores` (points per period, `|`-separated) and the same for `away…`; `winner` (abbreviation, or `DRAW`), `margin`, `totalScore`, `periods`, `overtime`; `venue`, `venueCity`, `venueState`, `venueCountry`, `attendance`, `neutralSite`, `conferenceGame`, `broadcasts`, `notes` (playoff round, rivalry name…), `headline` (recap title), `gameUrl`. Soccer adds `homeShootoutScore`/`awayShootoutScore`, `homeForm`/`awayForm`, `leg`, `round`, possession, shots, shots on target and corners for both sides. **Betting lines** (when ESPN shows them — upcoming games and many recent ones): `oddsProvider`, `oddsDetails` (`SEA -2.5`), `homeSpread` (home team's line; negative = home favoured), `overUnder`, `homeMoneyline`, `awayMoneyline`, `drawMoneyline` (soccer), `homeSpreadOdds`, `awaySpreadOdds`, `overOdds`, `underOdds`, `favoriteSide`, and opening lines `homeMoneylineOpen`, `awayMoneylineOpen`, `homeSpreadOpen`, `overUnderOpen`. With `includeGameDetails`: `officials`, `weather`, `temperatureF`, `windGustMph`, `precipitationChancePct`, `venueCapacity`, `grass`.

**Player box scores** — game context (`gameId`, `gameDate`, `teamId`, `team`, `teamAbbreviation`, `homeAway`, `opponentId`, `opponent`, `opponentAbbreviation`, `teamScore`, `opponentScore`, `result` W/L/D), the player (`athleteId`, `athleteName`, `jersey`, `position`, `starter`, `didNotPlay`, `dnpReason`, `ejected`, `athleteUrl`), `statGroup` (the ESPN box-score table: `passing`, `rushing`, `receiving`, `defensive`, `kicking` … in football; `batting` / `pitching` in baseball; `forwards`, `defenses`, `goalies` in hockey; `match` in soccer; empty in basketball) and the stats of that table with ESPN's own names. "Made-attempted" pairs are split into two numbers (`fieldGoalsMade` + `fieldGoalsAttempted`, `completions` + `passingAttempts`, `pitches` + `strikes`), innings pitched become `inningsPitched` + `outsRecorded`, and clock values such as hockey time on ice keep the `mm:ss` text plus a `…Seconds` number. In pitching rows `hits`, `runs`, `walks`, `strikeouts` and `homeRuns` are allowed by the pitcher.

**Team box scores** — the same game context plus every team statistic ESPN shows for the sport (basketball shooting, rebounds, turnovers, points in the paint, fast-break points, largest lead; football first downs, third/fourth-down conversions and attempts, total yards, passing/rushing, penalties and penalty yards, red-zone scores and attempts, possession time; hockey shots, power plays, faceoffs; soccer possession, shots, passes, crosses, tackles; baseball batting/pitching/fielding totals prefixed `batting…`, `pitching…`, `fielding…`).

**Play-by-play** — `gameId`, `gameDate`, `homeTeam`, `awayTeam`, `playId`, `sequence`, `period`, `periodLabel`, `clock`, `team`, `type`, `typeId`, `text`, `shortText`, `scoringPlay`, `scoreValue`, `homeScore`, `awayScore` (score after the play), `athlete1Id`/`athlete1Name`/`athlete1Role` … up to three players, `wallclock`. Football adds `driveNumber`, `driveId`, `driveTeam`, `driveResult`, `driveDescription`, `offenseTeam`, `defenseTeam`, `down`, `distance`, `yardLine`, `yardsToEndzone`, `possessionText`, `yardsGained`, `endDown`, `endDistance`, `endYardsToEndzone`, `isPenalty`, `isTurnover`. Basketball adds `shootingPlay`, `pointsAttempted`, `coordinateX`, `coordinateY`. Hockey adds `strength` and coordinates. Baseball adds `inningHalf`, `atBatId`, `batOrder`, `bats`, `pitchNumber`, `pitchType`, `pitchVelocity`, `pitchX`, `pitchY`, `balls`, `strikes`, `outs`. Soccer rows are the minute-by-minute commentary with `fieldPositionX`/`fieldPositionY`.

**Standings** — `season`, `seasonName`, `seasonType`, `group` (conference / league table), `subgroup` (division), `rank`, `teamId`, `team`, `teamAbbreviation`, then ESPN's columns for the sport: `wins`, `losses`, `ties`, `winPercent`, `gamesBehind`, `playoffSeed`, `clincher`, `streak`, `pointsFor`, `pointsAgainst`, `pointDifferential`, `points` (hockey/soccer), `gamesPlayed`, `rankChange`, `overallRecord`, `homeRecord`, `awayRecord`, `divisionRecord`, `conferenceRecord`, `lastTenRecord`, `note` (e.g. "Champions League"), `teamUrl`.

**Teams** — `teamId`, `team`, `abbreviation`, `location`, `nickname`, `shortName`, `slug`, `color`, `alternateColor`, `isActive`, `logo`, `record`, `standingSummary`, `venue`, `venueCity`, `venueState`, `nextGameDate`, `nextGame`, `teamUrl`, `rosterUrl`, `scheduleUrl`.

**Rosters** — `teamId`, `team`, `teamAbbreviation`, `athleteId`, `athleteName`, `firstName`, `lastName`, `jersey`, `position`, `positionName`, `positionGroup` (offense / defense / special teams / IR / practice squad in the NFL), `age`, `dateOfBirth`, `heightInches`, `height`, `weightLbs`, `weight`, `experienceYears`, `college`, `birthCity`, `birthState`, `birthCountry`, `status`, `injuryStatus`, `injuryDate`, `salary`, `headCoach`, `headshot`, `athleteUrl`.

**Injury reports** — `teamId`, `team`, `teamAbbreviation`, `athleteId`, `athleteName`, `position`, `status`, `fantasyStatus`, `injury`, `bodyPart`, `detail`, `side`, `returnDate`, `date`, `shortComment`, `longComment`, `athleteUrl`.

**Player game logs** — `athleteId`, `athleteName`, `season`, `seasonType`, `gameId`, `gameDate`, `week`, `teamId`, `team`, `homeAway`, `opponentId`, `opponent`, `opponentAbbreviation`, `result`, `teamScore`, `opponentScore` and the player's stat line with ESPN's names, newest season first.

**Tennis matches / UFC bouts** (games mode) — `eventId`, `event`, `eventStart`, `eventEnd`, `major`, `gameId`, `date`, `draw` (Men's Singles, Women's Doubles …), `round`, `weightClass` (UFC), `player1…` / `player2…` (`Id`, name, `Country`, `Seed`, `Winner`, `Record`, `Sets`, `SetsWon`), `winner`, `score` (from the winner's side, tiebreaks in brackets), `endRound` and `endTime` (UFC), `result`, `venue`, `court`. **Golf / F1** — games mode gives one row per tournament or Grand Prix; player box-score mode gives one row per player per tournament (position, score to par, round scores, total strokes) or per driver per session.

### How much data can I get?

Measured on the Apify platform on **2026-10-15** with default settings:

| Run | Rows | Time |
|---|---|---|
| NBA 2025-26, player box scores, regular season + playoffs (1,322 games) | **28,704** | 53 s |
| Premier League + LALIGA + Bundesliga + Serie A + Ligue 1 2024-25, player match stats (1,752 matches) | **54,295** | 68 s |
| NFL 2025 season, play-by-play (286 games) | **51,601** | 46 s |
| ATP + WTA 2025, every completed match | **12,447** | 8 s |
| NBA 2025-26, team box scores | **2,644** | 40 s |
| NFL + NBA current rosters | **3,189** | 4 s |
| NFL + NBA + NHL + MLB injury reports | **1,345** | 2 s |
| LeBron James + Patrick Mahomes career game logs | **2,096** | 2 s |
| 1,000 player box-score rows | 1,000 | 3 s |

Quality checks on those runs: 0 duplicate rows; in the NBA run every player line satisfies points = 2×FG + 3PM + FT and rebounds = offensive + defensive; 3,503 of 3,504 soccer team lines have exactly 11 starters, and players' goals (plus the opponent's own goals) add up to the final score in 3,502 of 3,504 team-matches — the two exceptions are a single match where ESPN's own data disagrees. Whole seasons are complete: 380 matches for the Premier League, LALIGA and Serie A, 306 for the Bundesliga and Ligue 1.

Bigger jobs simply take longer: a full NCAA Division I basketball season of box scores is roughly 100,000 player lines, several NBA seasons of play-by-play run into the millions. There is no cap other than your **Max rows** and the run's maximum cost.

### Speed

Rows appear in the Output tab within seconds and keep streaming in date order. The Actor reads month-sized scoreboards (day by day when a month holds more than 500 games, as in college basketball), then 24 game summaries in parallel. A full NBA season of box scores takes under a minute; 1,000 rows take about 3 seconds.

### What you pay

**Pay per result: a fixed price for every row saved — compute and network are included.** On the Apify Free plan it is $1.50 per 1,000 rows; paid Apify plans get the Store discount down to $1.00 per 1,000. Examples at the free-plan price: 1,000 rows = $1.50 · one NBA game's box score (~22 players) ≈ $0.03 · a full NBA season of player box scores (28,704 rows) ≈ $43 · a season of NBA standings (30 rows) ≈ $0.05.

**Maximum cost per run.** Apify lets you set a "Maximum cost per run" (also via the API parameter `maxTotalChargeUsd`). ESPN Scraper respects it exactly: it calculates how many rows the budget covers, stops there and finishes **successfully** with a message such as *"Saved 37 player box-score rows — this run's maximum cost ($0.05) covers 37 results."* You are never charged above your limit and the run is never aborted half-way. Raise the limit (or **Max rows**) when you want more.

### Integrations

**Apify API (curl)** — start a run and get the rows in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/logiover~espn-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"mode":"games","leagues":["nfl"],"dateFrom":"today","dateTo":"+7 days","includeGameDetails":true}'
```

**Python:**

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_TOKEN")
run = client.actor("logiover/espn-scraper").call(run_input={
    "mode": "playerStats", "leagues": ["nba"], "seasons": ["2025-26"], "maxItems": 0})
rows = list(client.dataset(run["defaultDatasetId"]).iterate_items())
```

**Node.js:**

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('logiover/espn-scraper').call({ mode: 'standings', leagues: ['nba'], seasons: ['2024-25'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

- **Google Sheets** — export the dataset to Sheets or schedule the run and push new rows with the Google Sheets integration.
- **Make, Zapier, n8n** — use the Apify app/node: "Run Actor" → "Get dataset items", e.g. post tonight's lines to Slack or Discord.
- **Webhooks** — get notified when a run finishes and fetch the dataset.
- **Schedules** — run daily for yesterday's box scores (`dateFrom: "yesterday"`) or upcoming games with odds.
- **AI agents (MCP)** — add the Actor to Claude, ChatGPT or Cursor through Apify's MCP server and ask for "last night's NBA box scores".

### ESPN Scraper vs. other ways to get ESPN data

| | ESPN Scraper | Copying from espn.com | Writing your own client for ESPN's hidden API |
|---|---|---|---|
| Whole seasons in one run | ✅ months/days handled for you | ❌ one game at a time | ⚠️ you must find the right endpoints, page sizes and day-splitting |
| Clean flat columns, joinable IDs | ✅ | ❌ | ⚠️ ESPN returns positional stat arrays and nested JSON |
| Box scores for every sport's layout | ✅ basketball, football groups, batting/pitching, skaters/goalies, soccer | ❌ | ⚠️ different structure per sport |
| Betting lines, injuries, rosters, game logs | ✅ one Actor | ❌ | ⚠️ several more endpoints |
| Handles ESPN's occasional "Access Denied" | ✅ automatic retry and proxy fallback | — | ❌ your job |
| Exports, schedules, API, integrations | ✅ built in | ❌ | ❌ |

### Limits and good to know

- **Season naming:** use `2025-26` style when unsure. ESPN's own season year is shown in every row.
- **Odds** are the lines ESPN shows (currently DraftKings); upcoming games and most recent seasons have them, older games often do not.
- **Rosters and injuries are current** — ESPN does not publish historical rosters. For who played in past games use player box scores.
- **College sports** include every Division I game (men's and women's basketball) and every FBS game (football; FCS via `college-football-fcs`).
- **Golf and Formula 1:** ESPN publishes leaderboards and session classifications only (no lap times or strokes-gained).
- **Play-by-play** availability depends on the sport and league; NFL, college football, NBA, WNBA, college basketball, NHL, MLB and the big soccer leagues have it.
- Data appears as soon as ESPN publishes it; live games show their current score and status.

### FAQ

#### Is there an official ESPN API?

ESPN closed its public developer API years ago. ESPN Scraper reads the public JSON behind espn.com and the ESPN app, so you get the same data without an API key.

#### Do I need an ESPN account, login or API key?

No. Everything ESPN Scraper reads is public.

#### How do I get every game of a season?

Choose *Games & scores*, select the league and enter the season (e.g. `2025-26`) with **Max rows** set to 0.

#### How do I get NBA (or NFL, MLB, NHL) box scores for a whole season?

Choose *Player box scores*, select the league and season, set **Max rows** to 0. A full NBA season is about 28,700 rows and takes under a minute.

#### Can I get play-by-play data?

Yes — mode *Play-by-play*. Football rows include down, distance and yard line; baseball rows include pitch type, velocity and count; basketball and hockey rows include shot coordinates.

#### Does it include betting odds?

Yes. Games mode adds the spread, total and moneylines ESPN shows (currently DraftKings), including opening lines for upcoming games. Turn on *Add officials, closing odds and weather* for closing lines of finished games.

#### Which soccer leagues are supported?

All major leagues and cups in the list, plus any other league ESPN covers via its code in *Other ESPN leagues* (for example `soccer/ger.2` for the 2. Bundesliga).

#### Can I scrape tennis, UFC or golf?

Yes. ATP and WTA give every match of every tournament with set scores; UFC gives every bout with weight class, winner, round and time; PGA and LPGA give leaderboards with round scores.

#### How do I get a player's career game log?

Mode *Player game logs*, then enter the player's name or ESPN URL in **Players**. Leave **Seasons** empty for the whole career.

#### How fresh is the data?

It is read live from ESPN at run time. Schedule the Actor (e.g. every morning with `dateFrom: "yesterday"`) to keep a database up to date.

#### Can I filter by team?

Yes — **Only these teams** accepts abbreviations, names or ESPN team IDs and works for games, box scores, play-by-play, standings, rosters and injuries.

#### How much does it cost?

$1.50 per 1,000 rows on the Apify Free plan, down to $1.00 per 1,000 on paid plans. No other charges. Set a maximum cost per run and the Actor stops exactly there.

#### What happens if ESPN blocks a request?

ESPN occasionally answers one request with "Access Denied". The Actor retries at once and switches to the Apify proxy if refusals pile up. If ESPN could not be reached at all, the run fails with a clear message instead of returning an empty dataset that looks like "no games".

#### Can I use the data in Excel or Google Sheets?

Yes. Download CSV or Excel from the Output/Storage tab, or connect Google Sheets.

#### Is it suitable for machine learning and betting models?

Yes — rows are flat, typed (numbers are numbers), deduplicated and keyed by ESPN IDs, so multiple seasons and modes join cleanly.

### Is scraping ESPN legal?

ESPN Scraper only collects publicly available sports facts (scores, statistics, schedules) that ESPN publishes without a login. Sports results and statistics are generally treated as facts. You are responsible for how you use the data: respect ESPN's terms of use, do not republish ESPN's articles, photos or videos, and check the rules that apply to your use case and country. If in doubt, consult a lawyer.

**Disclaimer:** This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by ESPN, Inc., The Walt Disney Company or any league mentioned. All trademarks are the property of their respective owners.

### Changelog

- **1.0 (2026-10-15)** — First release: games & scores with betting lines, player and team box scores, play-by-play, standings, teams, rosters, injury reports and player game logs for 50+ leagues; whole seasons or date ranges; tennis, UFC, golf and Formula 1 results; maximum-cost-per-run support.

### Support

Questions, a league or field you need, or a run that did not do what you expected? Open an issue on the Actor's **Issues** tab — we reply within 24 hours and usually ship requested fields within a few days.

# Changelog

This Actor's version history is a separate document: https://apify.com/logiover/espn-scraper/changelog.md

# Actor input Schema

## `mode` (type: `string`):

Which ESPN data to collect. Games, player and team box scores and play-by-play cover whole seasons or any date range; standings work for past seasons too; teams, rosters and injuries are the current ones.

## `leagues` (type: `array`):

One or more leagues. NFL, NBA, MLB, NHL, WNBA, college football and basketball (all Division I games), MLS, Premier League, LALIGA, Bundesliga, Serie A, Ligue 1, Champions League and more, plus ATP/WTA tennis, UFC, PGA/LPGA golf and Formula 1.

## `customLeagues` (type: `array`):

Any other league ESPN covers, as its ESPN path or code: "soccer/ger.2" (2. Bundesliga), "soccer/esp.2", "basketball/nba-summer-las-vegas", or an ESPN league URL such as https://www.espn.com/soccer/league/\_/name/ger.2.

## `seasons` (type: `array`):

Whole seasons, e.g. "2025-26" or "2026". "2025-26" works for every league (NBA/NHL: the 2025-26 season; NFL/MLB: 2025; soccer: the 2025-26 season). A plain year is ESPN's own season year: NBA/NHL/college basketball count the year the season ends (2026 = 2025-26), NFL/MLB/WNBA/MLS the calendar year, European soccer the year it starts. Leave empty to use the date range.

## `seasonType` (type: `string`):

Which games of a season to keep (US-style leagues; soccer competitions, tennis and golf are always complete). Automatic keeps the regular season and playoffs when you ask for whole seasons, and every game when you give a date range.

## `dateFrom` (type: `string`):

Start date when no season is given: YYYY-MM-DD or relative like "7 days" (7 days ago), "yesterday", "today". Empty = 3 days ago for games, 7 days ago for box scores and plays.

## `dateTo` (type: `string`):

End date (inclusive): YYYY-MM-DD or relative like "+7 days" (a week ahead — upcoming schedule), "today". Empty = a week ahead for games, today for box scores.

## `teams` (type: `array`):

Keep only games, players, standings rows and rosters of these teams: abbreviation ("LAL"), name ("Lakers", "Boston Celtics") or ESPN team ID. Empty = all teams.

## `onlyCompleted` (type: `boolean`):

Games mode: leave out scheduled and live games (they are included by default, so the same run gives results and the upcoming schedule with betting lines). Box scores and plays always use finished games.

## `gameIds` (type: `array`):

ESPN game URLs (https://www.espn.com/nba/game/\_/gameId/401585183/...) or game IDs. When given, the games, box-score and play-by-play modes read exactly these games instead of a season or date range. Bare IDs use the first selected league.

## `athletes` (type: `array`):

For "Player game logs": ESPN player URLs (https://www.espn.com/nba/player/\_/id/1966/lebron-james), player IDs (with the league selected above) or names ("Patrick Mahomes"). Without seasons you get the whole career.

## `includeDidNotPlay` (type: `boolean`):

Player box scores: also add rows for players listed as DNP/inactive/unused substitute, with the reason ("COACH'S DECISION", injuries).

## `includeGameDetails` (type: `boolean`):

Games mode: read each game's summary too and add referees/umpires, DraftKings/ESPN BET closing lines (spread, total, moneylines, over/under odds), weather and venue capacity. One extra request per game.

## `includeTeamDetails` (type: `boolean`):

Teams mode: add the current record, standing summary ("1st in Atlantic Division"), home venue and next game. One extra request per team.

## `maxItems` (type: `integer`):

Stop after this many rows in total. 0 = no limit. A full NBA season is ~1,300 games, ~30,000 player box-score rows or ~600,000 plays.

## `concurrency` (type: `integer`):

How many ESPN requests run at the same time. The default reads a full NBA season of box scores (~1,300 games) in about a minute.

## `proxyConfiguration` (type: `object`):

ESPN is read directly first. If it starts refusing requests, the run switches to this proxy for a while. Leave the Apify proxy on.

## Actor input object example

```json
{
  "mode": "games",
  "leagues": [
    "nba"
  ],
  "customLeagues": [],
  "seasons": [
    "2025-26"
  ],
  "seasonType": "auto",
  "teams": [],
  "onlyCompleted": false,
  "gameIds": [],
  "athletes": [],
  "includeDidNotPlay": false,
  "includeGameDetails": false,
  "includeTeamDetails": true,
  "maxItems": 200,
  "concurrency": 24,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All rows collected in this run.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "mode": "games",
    "leagues": [
        "nba"
    ],
    "seasons": [
        "2025-26"
    ],
    "maxItems": 200,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("logiover/espn-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "mode": "games",
    "leagues": ["nba"],
    "seasons": ["2025-26"],
    "maxItems": 200,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("logiover/espn-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "mode": "games",
  "leagues": [
    "nba"
  ],
  "seasons": [
    "2025-26"
  ],
  "maxItems": 200,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call logiover/espn-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,logiover/espn-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/zWpR3pcVzTbYuhz9y/builds/K4i8gElGyP4LKwTnN/openapi.json
