# ESPN Scores, Schedules & Odds Scraper (`automatic/espn-sports`) Actor

Collect ESPN fixtures, live and final scores, team records, venue and broadcast for the NFL, NBA, NHL, MLB, college sports, soccer and UFC, with the sportsbook moneyline, spread and total ESPN shows for each game (opening and current). Optional standings, teams, rosters and futures.

- **URL**: https://apify.com/automatic/espn-sports.md
- **Developed by:** [Philip Kirkbride](https://apify.com/automatic) (community)
- **Categories:** Sports
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 Scores, Schedules & Odds Scraper

Collect ESPN fixtures, live and final scores, team records, venue and
broadcast for the NFL, NBA, NHL, MLB, college football and basketball, 18
soccer leagues and UFC, one record per game, together with the sportsbook
lines ESPN shows for that game: moneyline, spread and total, each with its
opening and current value, American and decimal odds and the implied
probability. Optional extras: standings, teams, rosters and sportsbook futures
boards. Built for sports-data analysts, bettors, fantasy and model builders who
schedule runs and pipe the JSON into dashboards, alerts or models. No ESPN
account or API key is needed.

Data only, not betting or financial advice. This is an unofficial tool: it is
not affiliated with or endorsed by ESPN or any sportsbook.

### Use cases

- **Scoreboards and schedules:** today's games and the next few days for the
  leagues you follow, with kickoff times in UTC, status, scores, period and
  clock.
- **Line tracking:** opening versus current moneyline, spread and total per
  game; schedule runs to chart how a line moves before the start.
- **Closing-line studies:** final scores next to the opening and closing lines
  of the same game, for model back-testing.
- **Cross-book comparison:** join each game with prediction-market or exchange
  records on sport, league, participants and start time through the shared
  `canonicalMarkets` envelopes. Home and away are explicit here.
- **Reference data:** standings tables, team lists, rosters and futures boards
  (title winner, MVP and more) to enrich your own tables.

### Quick start

1. Open the Actor and click **Start**. The prefilled form collects NFL, NBA and MLB
   games for today and the next three days, with their lines.
2. Read the rows in the **Output** tab, or export them as JSON, CSV or Excel.

One league on chosen days:

```json
{"leagues": ["epl"], "dateFrom": "2026-11-21", "dateTo": "2026-11-23"}
```

Yesterday's results with opening and closing lines:

```json
{"leagues": ["nba"], "dateFrom": "2026-11-09", "includeClosingOdds": true}
```

Standings, teams and futures for one league:

```json
{"leagues": ["nfl"], "collect": ["standings", "teams", "futures"], "maxResults": 1000}
```

Leaving `leagues` empty collects the default scope: NFL, NBA and MLB events
for today and the next three days (MLB covers the summer, when the other two
are out of season). When none of the three has a game in that window the run
stops with a message that says so and asks you to pick leagues and dates; it
never widens the scope by itself.

An empty input (`{}`, no leagues, dates or `maxResults` at all) is a sample:
the default scope, at most 20 records, and the run's status message says it
was a sample. Set any of those fields (the prefilled form does) for a full
run of up to 500 records.

### Input

| Name | Type | Default | What it does |
| --- | --- | --- | --- |
| `leagues` | array | NFL, NBA and MLB | Leagues to collect: `nfl`, `ncaaf`, `nba`, `wnba`, `ncaab`, `ncaaw`, `mlb`, `nhl`, `epl`, `laliga`, `seriea`, `bundesliga`, `ligue_1`, `ucl`, `uel`, `mls`, `liga_mx`, `brasileirao`, `argentina_primera`, `eredivisie`, `primeira_liga`, `belgian_pro_league`, `scottish_premiership`, `super_lig`, `chile_primera`, `j1_league`, `ufc`. |
| `collect` | array | `["events"]` | Any of `events`, `standings`, `teams`, `rosters`, `futures`. |
| `dateFrom` / `dateTo` | string | today to today + 3 | Game days as `YYYY-MM-DD` (US Eastern calendar days). With only `dateFrom`, that single day. At most 31 days, and leagues × days at most 120. |
| `includeOdds` | boolean | `true` | Add the sportsbook lines shown for each game. |
| `includeClosingOdds` | boolean | `false` | Also look up the opening and closing lines of games that have started or finished (one extra lookup per such game, at most 100 per run). Needs `includeOdds`. |
| `includeAllCollegeGames` | boolean | `true` | Every FBS / Division I game instead of only games involving ranked teams. |
| `maxResults` | integer | `500` | Maximum dataset records per run (1–5,000), across all record kinds. Left empty in a run that also sets no leagues or dates, it is 20 (the sample). |
| `requestDelaySecs` | number | `1` | Seconds between requests (0.25–10). |

A misspelt input field, an unsupported league or a window over the limits
stops the run with an error that names the problem. Rosters are limited to three
leagues per run and 40 teams per league.

### Output

Every record has `kind`: `event`, `standing`, `team`, `athlete` or `future`.
All records share the same fields; fields that do not apply to a kind are
`null` (lists are empty).

**Event records** (one per game; one per bout for UFC):

- **Identity:** `recordKey`, `eventId`, `sport`, `league`, `leagueLabel`,
  `seasonYear`, `seasonType`, `week`, `title`, `sourceUrl`.
- **Timing and state:** `startTime` (UTC), `startTimeTbd`, `status`
  (`scheduled`, `in_progress`, `final`, `postponed`, `canceled`, `delayed`,
  `suspended` or `unknown`), `statusNative`, `statusDetail`, `period`, `clock`.
- **Sides:** `home` and `away` with `name`, `abbreviation`, `score`, `winner`,
  `record`, `rank` and per-period `linescores`; `competitors` lists both, and
  `participants` the two names. Scores are `null` until a game starts, never a
  placeholder zero. UFC fighters are not home or away, so `home` and `away`
  are `null` there and the card's name is in `cardName`.
- **Where to watch:** `venue` (name, city, state, country, indoor),
  `neutralSite`, `broadcasts`, `notes`.
- **Lines:** `oddsAvailable` and `odds`, one entry per sportsbook:
  - `moneyline.home`, `.away` and, for soccer, `.draw`;
  - `spread.home` and `.away`, each with its `line`;
  - `total.over` and `.under`, each with its `line`;
  - every side has `open` and `current`, each a price with `american`,
    `decimal` and `impliedProbability`;
  - `provider`, `details` (the sportsbook's one-line summary) and
    `lastUpdated` (always `null` for now: no update time is published for
    these lines; use `collectedAt`).
- **`canonicalMarkets`:** the same lines as one shared envelope per market, in
  the format our other sports Actors use, for joining across sources.

How to read the lines:

- `impliedProbability` is `1 / decimal` of that single price. It includes the
  bookmaker's margin, so the sides of a market add up to more than 1.
- `current` is the line shown when the run read the game. For a finished game
  collected with `includeClosingOdds` it is the closing line.
- `spread.home.current.line` of `-2.5` means the home team gives 2.5 points.
- Anything not published is `null`: a missing side, a line without a price or
  a game without lines (`odds: []`, `oddsAvailable: false`). No value is
  estimated or filled in from the other side.

**Other records:** `standing` (table, team, rank, wins, losses, ties, points,
record, streak, note), `team` (id, name, abbreviation, location, colours),
`athlete` (name, jersey, position, height, weight, age, experience, college,
status, team) and `future` (board, selection, price). Futures name their
selection by id; the name is filled in for teams, and for players when
`rosters` is collected in the same run.

The run summary (`OUTPUT` in the key-value store) reports records per kind,
events with and without lines per league, requests made, warnings and the
status `succeeded`, `succeeded_empty`, `succeeded_partial` or `failed`, and
`sampleRun: true` for the empty-input sample. The same one-line summary is the
run's status message.

### Output example

Selected fields of a real NFL game collected 2026-11-10 (full records also
carry `competitors`, `canonicalMarkets`, `statusNative`, `notes` and the
other fields listed above):

```json
{"recordKey":"espn:event:nfl:401873052","source":"espn","kind":"event","sourceUrl":"https://www.espn.com/nfl/game/_/gameId/401873052/commanders-giants","sport":"american_football","league":"nfl","leagueLabel":"NFL","seasonYear":2026,"seasonType":2,"eventId":"401873052","title":"Washington Commanders at New York Giants","shortName":"WSH @ NYG","startTime":"2026-11-13T01:15:00+00:00","status":"scheduled","statusDetail":"11/12 - 8:15 PM EST","week":10,"neutralSite":false,"participants":["New York Giants","Washington Commanders"],"home":{"id":"19","name":"New York Giants","abbreviation":"NYG","score":null,"record":"5-2-1"},"away":{"id":"28","name":"Washington Commanders","abbreviation":"WSH","score":null,"record":"2-5-1"},"venue":{"id":"3839","name":"MetLife Stadium","city":"East Rutherford","state":"NJ","country":"USA","indoor":false},"broadcasts":["Prime Video"],"oddsAvailable":true,"odds":[{"provider":"DraftKings","providerId":"100","details":"NYG -2.5","source":"scoreboard","currentBasis":"close","lastUpdated":null,"moneyline":{"home":{"open":{"american":-125,"decimal":1.8,"impliedProbability":0.5556},"current":{"american":-130,"decimal":1.7692,"impliedProbability":0.5652}},"away":{"open":{"american":105,"decimal":2.05,"impliedProbability":0.4878},"current":{"american":110,"decimal":2.1,"impliedProbability":0.4762}},"draw":null},"spread":{"home":{"open":{"line":-1.5,"american":-110,"decimal":1.9091,"impliedProbability":0.5238},"current":{"line":-2.5,"american":-110,"decimal":1.9091,"impliedProbability":0.5238}},"away":{"open":{"line":1.5,"american":-110,"decimal":1.9091,"impliedProbability":0.5238},"current":{"line":2.5,"american":-110,"decimal":1.9091,"impliedProbability":0.5238}}},"total":{"over":{"open":{"line":47.5,"american":-110,"decimal":1.9091,"impliedProbability":0.5238},"current":{"line":41.5,"american":-105,"decimal":1.9524,"impliedProbability":0.5122}},"under":{"open":{"line":47.5,"american":-110,"decimal":1.9091,"impliedProbability":0.5238},"current":{"line":41.5,"american":-115,"decimal":1.8696,"impliedProbability":0.5349}}}}],"collectedAt":"2026-11-10T23:10:16.420732+00:00"}
```

### Pricing

Pay per result: **$0.002 per dataset record** (event, standings row, team,
roster athlete or futures selection) plus **$0.00005 per run start**.

Worked examples, sizes measured 2026-11-11:

| Run | Records | Cost |
| --- | --- | --- |
| Empty input (`{}`), the sample | 20 | 20 × $0.002 + $0.00005 = $0.04005 |
| The prefilled form (NFL, NBA and MLB, four days; MLB out of season) | 29 | 29 × $0.002 + $0.00005 = $0.05805 |
| One Premier League weekend (21–23 Nov) | 10 | 10 × $0.002 + $0.00005 = $0.02005 |
| NFL standings, teams and futures together | 561 | 561 × $0.002 + $0.00005 = $1.12205 |
| A run that matches nothing | 0 | $0.00005 |

Use `leagues`, the date window and `maxResults` to keep runs small:
`maxResults` caps the record charge at `maxResults` × $0.002 per run. With a
maximum charge set on the run, the Actor stops at the last record that fits
and says so in the run summary.

### Scheduling and monitoring

- **Line movement:** schedule a league-scoped run (for example hourly on game
  days) and key your history on `recordKey` plus `collectedAt`.
- **Live scores:** schedule a run for today's date every few minutes while
  games are on; `status`, `period`, `clock` and scores update on each run.
- **Results with closing lines:** run once a day for yesterday's date with
  `includeClosingOdds`.
- Records are a fresh snapshot each run; nothing is remembered between runs.
  De-duplicate on `recordKey`.

### How many games have lines

Measured on 2026-11-10; it changes through the week and the season.

| League | Games checked | With lines |
| --- | --- | --- |
| NFL (Thu 12 Nov, Sun 15 Nov) | 13 | 13 |
| NBA, same day | 6 | 6 |
| NBA, next day | 10 | 5 |
| NBA, 2–3 days ahead | 13 | 0 |
| NHL, same day | 7 | 7 |
| NHL, 4 days ahead | 14 | 0 |
| College football (Sat 14 Nov) | 56 | 56 |
| Men's college basketball, same day | 69 | 56 |
| Men's college basketball, 4 days ahead | 72 | 0 |
| Women's college basketball, same day (not started) | 37 | 1 |
| Premier League (21–23 Nov) | 10 | 10 |
| La Liga, Serie A, Bundesliga, Ligue 1 (21–22 Nov) | 33 | 32 |
| MLS, Liga MX, Brasileirao (21–22 Nov) | 18 | 0 |
| UFC card (14 Nov) | 12 | 0 |
| Any game already started or finished | – | 0 without `includeClosingOdds` |
| NBA, finished the day before, with `includeClosingOdds` | 8 | 8 |

### FAQ

**Which sportsbook are the lines from?** The one ESPN shows for the game. On
2026-11-10 that was DraftKings for every game with lines. Finished games can
carry a second entry with the last in-play prices.

**Why does a game have no lines?** Lines are usually published one or two days
before a game (earlier for the NFL, college football and the big European
soccer leagues), often not at all for UFC and smaller competitions, and they
are removed from game listings once the game starts. Use `includeClosingOdds`
for started and finished games.

**How fresh is the data?** Each run reads ESPN at run time; nothing is cached
between runs.

**Can I get a whole season?** Up to 31 days per run. Split longer periods
into several runs.

**Are doubleheaders and rescheduled games handled?** Each game has its own
`eventId`, so both games of a doubleheader are separate records. A postponed
game keeps `status: "postponed"` with no score.

**Export formats?** JSON, CSV, Excel, XML or RSS from the dataset, or read it
through the Apify API in your own pipeline.

### Limits

- The data comes from an unofficial, undocumented source that can change or
  become unavailable without notice. Check a run's status and warnings before
  relying on it.
- One sportsbook's lines as shown by ESPN, not a multi-book odds feed. No
  player props, alternate lines or historical line series; build history by
  scheduling runs.
- Not supported: boxing, AHL, CFL, Euroleague, tennis, golf and motor racing.
- No play-by-play, box scores, news, video or win-probability data.
- Team logos and player photos are not included.
- Futures selections for players have no name unless `rosters` is collected
  in the same run.
- You are responsible for using the data in line with the terms of the sites
  it comes from and the laws that apply to you.

For support, contact Apify support and include the Actor run ID.

# Actor input Schema

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

Leagues to collect. Leave empty to collect the default scope (NFL, NBA and MLB); that default run stops with a clear message when none of the three has a game in the date window. A run that sets no leagues, dates or maximum at all is a sample of at most 20 records.

## `collect` (type: `array`):

events: fixtures and scores with the sportsbook lines shown for each game (one request per league per day). standings: league tables. teams: the league's teams. rosters: every team's players (one request per team, at most 3 leagues per run). futures: sportsbook futures boards such as the title winner or MVP, where they exist (NFL, NBA, NHL, MLB and college football and basketball had boards on 2026-11-10).

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

First game day to collect, as YYYY-MM-DD (US Eastern calendar day, the day the source lists games under). Leave both dates empty for today and the next 3 days. With only this date set, that single day is collected.

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

Last game day to collect, as YYYY-MM-DD. A window may cover at most 31 days, and leagues x days at most 120.

## `includeOdds` (type: `boolean`):

Add the moneyline, spread and total shown for each game, with opening and current values. Games without published lines get an empty odds list.

## `includeClosingOdds` (type: `boolean`):

Game listings stop showing lines once a game starts. Turn this on to look up the opening and closing lines of started and finished games (one extra request per such game, at most 100 per run). Needs "Include sportsbook lines" on.

## `includeAllCollegeGames` (type: `boolean`):

For college football and basketball, collect every FBS / Division I game instead of only games involving ranked teams.

## `maxResults` (type: `integer`):

Stop after this many dataset records in total, across events, standings rows, teams, roster athletes and futures selections. Left empty it is 500, or 20 for a run that also sets no leagues or dates (a sample).

## `requestDelaySecs` (type: `number`):

Seconds between request starts. The default of 1 keeps the run to about one request per second.

## Actor input object example

```json
{
  "leagues": [
    "nfl",
    "nba",
    "mlb"
  ],
  "collect": [
    "events"
  ],
  "includeOdds": true,
  "includeClosingOdds": false,
  "includeAllCollegeGames": true,
  "maxResults": 500,
  "requestDelaySecs": 1
}
```

# Actor output Schema

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

No description

## `summary` (type: `string`):

No description

# 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 = {
    "leagues": [
        "nfl",
        "nba",
        "mlb"
    ],
    "collect": [
        "events"
    ],
    "includeOdds": true,
    "includeClosingOdds": false,
    "includeAllCollegeGames": true,
    "maxResults": 500,
    "requestDelaySecs": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("automatic/espn-sports").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 = {
    "leagues": [
        "nfl",
        "nba",
        "mlb",
    ],
    "collect": ["events"],
    "includeOdds": True,
    "includeClosingOdds": False,
    "includeAllCollegeGames": True,
    "maxResults": 500,
    "requestDelaySecs": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("automatic/espn-sports").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 '{
  "leagues": [
    "nfl",
    "nba",
    "mlb"
  ],
  "collect": [
    "events"
  ],
  "includeOdds": true,
  "includeClosingOdds": false,
  "includeAllCollegeGames": true,
  "maxResults": 500,
  "requestDelaySecs": 1
}' |
apify call automatic/espn-sports --silent --output-dataset

```

## MCP server setup

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

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/SINak0d5dVhuz39uH/builds/BKq8VwO06tuTC4h19/openapi.json
