# Sports Scores & Betting Odds API: NFL, NBA, MLB, NHL, Soccer (`datagleaner/sports-scores-odds`) Actor

Sports scores, schedules and betting odds API from ESPN's public scoreboard: NFL, NBA, MLB, NHL, college football and basketball, Premier League, La Liga, Champions League and more. Spread, total, moneylines, live and final scores. $1.00 per 1,000 games. No login, no API key.

- **URL**: https://apify.com/datagleaner/sports-scores-odds.md
- **Developed by:** [Data Gleaner](https://apify.com/datagleaner) (community)
- **Categories:** Sports, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 games

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

## Sports Scores & Betting Odds API: NFL, NBA, MLB, NHL, Soccer

**Get sports scores, schedules and betting odds as clean JSON: one row per game for the NFL, NBA, MLB, NHL, WNBA, college football and basketball, the Premier League, La Liga, Serie A, Bundesliga, Ligue 1, MLS, the Champions League and more.** Each row has the matchup, start time, live or final score, period scores, venue, TV channels, and the posted odds: point spread, over/under total, and moneylines for home, away and (in soccer) the draw, with the opening line next to the current one. Data comes from ESPN's public scoreboard. No login, no API key, no browser. **$1.00 per 1,000 games.**

#### Why this one

- **Scores and odds in one row.** No second call to join a game to its line: `homeTeam.score`, `awayTeam.score`, `odds.spread`, `odds.overUnder`, `odds.homeMoneyline` are in the same record.
- **Opening and current lines.** `odds.open` holds the opening spread, total and moneylines, so you can see line movement without running a scheduler.
- **Past, live and future days.** Pick a date range to pull final scores for backtesting or upcoming games with odds for a model. Leave the dates empty for the current scoreboard.
- **21 leagues, one input.** Multi-select the leagues; every row says which league it came from.
- **Plain HTTP, no proxy needed.** It reads ESPN's public JSON from Apify's servers and was tested from Apify's datacenter IPs.
- **You cap the cost.** `maxGames` limits the rows, and a maximum total charge on the run stops it cleanly.

#### Minimal input

```json
{"leagues": ["nfl", "nba"], "maxGames": 50}
```

An empty input runs a built-in example: the current scoreboard of one league, at most 5 games.

#### Sample output row

A real row from ESPN's NFL scoreboard on 2026-10-21 (before kickoff, so no score yet):

```json
{
  "league": "nfl",
  "leagueName": "NFL",
  "sport": "football",
  "eventId": "401873010",
  "name": "New England Patriots at Chicago Bears",
  "shortName": "NE @ CHI",
  "startTime": "2026-10-23T00:15:00Z",
  "status": "scheduled",
  "statusDetail": "Thu, October 22nd at 8:15 PM EDT",
  "period": null,
  "clock": null,
  "season": 2026,
  "week": 7,
  "neutralSite": false,
  "venue": {"name": "Soldier Field", "city": "Chicago", "state": "IL", "country": "USA"},
  "broadcasts": ["Prime Video"],
  "homeTeam": {"id": "3", "name": "Chicago Bears", "shortName": "Bears", "abbreviation": "CHI", "score": null, "record": "4-2", "winner": null, "linescores": [], "rank": null},
  "awayTeam": {"id": "17", "name": "New England Patriots", "shortName": "Patriots", "abbreviation": "NE", "score": null, "record": "4-2", "winner": null, "linescores": [], "rank": null},
  "odds": {
    "provider": "Draft Kings",
    "details": "CHI -3",
    "favorite": "CHI",
    "spread": -3.0,
    "overUnder": 50.5,
    "homeMoneyline": -155,
    "awayMoneyline": 130,
    "drawMoneyline": null,
    "homeSpreadOdds": -102,
    "awaySpreadOdds": -118,
    "overOdds": -115,
    "underOdds": -105,
    "open": {"homeMoneyline": -120, "awayMoneyline": 100, "drawMoneyline": null, "homeSpread": -1.5, "awaySpread": 1.5, "homeSpreadOdds": -105, "awaySpreadOdds": -115, "total": 47.5, "overOdds": -110, "underOdds": -110}
  },
  "espnUrl": "https://www.espn.com/nfl/game/_/gameId/401873010/patriots-bears",
  "scrapedAt": "2026-10-21T15:50:02Z",
  "input": "nfl"
}
```

### What does Sports Scores & Betting Odds API do?

- Reads ESPN's scoreboard for each league you choose, for today or for each day of a date range.
- Returns one flat, typed row per game: scores as numbers, times in ISO 8601 UTC, odds as numbers (American moneylines such as -155 and +130).
- Marks each game `scheduled`, `in progress`, `final`, `postponed`, `canceled`, `suspended`, `forfeit` or `abandoned`, with ESPN's own text in `statusDetail` ("Final/OT", "Halftime", "5:12 - 3rd Quarter").
- Optionally keeps only games that have odds posted (`onlyWithOdds`).

Typical uses: sports betting models and odds comparison inputs, fantasy and DFS research, score and schedule widgets, Discord and Telegram bots, sports data for LLM agents, historical results for backtests, line-movement tracking (schedule it daily and compare `odds`).

### Leagues

| Input value | League |
|---|---|
| `nfl`, `nba`, `mlb`, `nhl`, `wnba` | NFL, NBA, MLB, NHL, WNBA |
| `college-football` | NCAA football, FBS (all games of the day) |
| `mens-college-basketball`, `womens-college-basketball` | NCAA basketball, Division I |
| `eng.1`, `eng.2` | English Premier League, Championship |
| `esp.1`, `ita.1`, `ger.1`, `fra.1` | La Liga, Serie A, Bundesliga, Ligue 1 |
| `usa.1`, `mex.1` | MLS, Liga MX |
| `ned.1`, `por.1`, `sco.1` | Eredivisie, Primeira Liga, Scottish Premiership |
| `uefa.champions`, `uefa.europa` | Champions League, Europa League |

Also accepted as shortcuts: `epl`, `mls`, `ncaaf`, `ncaab`, `ncaaw`, `laliga`, `serie-a`, `bundesliga`, `ligue-1`. UFC and golf are not included in this version: they have fight cards and leaderboards, not home/away games.

### Input

| Field | Type | What it does |
|---|---|---|
| `leagues` | list of choices | One or more leagues from the table above. Prefilled with `nfl` and `nba`. |
| `dateFrom` | date, `YYYY-MM-DD` | First day (ESPN schedule day, US Eastern). Empty with an empty `dateTo` means the current scoreboard. |
| `dateTo` | date, `YYYY-MM-DD` | Last day. Empty means the same day as `dateFrom`. Up to 92 days, one request per day per league. |
| `onlyWithOdds` | yes/no | Default no. Keep only games with odds posted. |
| `maxGames` | number | Default 500 (prefill 10). Stops after this many rows in total; also your cost cap. |
| `requestDelaySeconds` | number | Pause before each request, default 0.2. |
| `proxyConfiguration` | object | Optional Apify Proxy. Default none; ESPN answers Apify's servers without it. |

```json
{
  "leagues": ["nfl"],
  "dateFrom": "2026-10-25",
  "dateTo": "2026-10-26",
  "onlyWithOdds": true,
  "maxGames": 50
}
```

#### What "current scoreboard" returns

With no dates, ESPN returns its default window for each league: today's games for the NBA, NHL, MLB and soccer leagues, and the whole current week for the NFL and college football (for example the NFL's week 7, Thursday to Monday). Use dates when you need an exact window.

### Output

One row per game. Every key is always present; a value is `null` when it does not apply.

- **Game:** `league`, `leagueName`, `sport`, `eventId`, `name`, `shortName`, `startTime`, `status`, `statusDetail`, `period`, `clock`, `season`, `week`, `neutralSite`, `venue` (`name`, `city`, `state`, `country`), `broadcasts`, `espnUrl`.
- **Teams:** `homeTeam` and `awayTeam`, each with `id`, `name`, `shortName`, `abbreviation`, `score`, `record`, `winner`, `linescores` (points or goals per quarter, half, period or inning) and `rank` (college poll rank).
- **Odds:** `odds` with `provider`, `details`, `favorite`, `spread` (from the home team's side: negative means the home team is favored), `overUnder`, `homeMoneyline`, `awayMoneyline`, `drawMoneyline`, `homeSpreadOdds`, `awaySpreadOdds`, `overOdds`, `underOdds`, and `open` with the opening values of the same lines.
- **Run info:** `scrapedAt` and `input` (the league that produced the row).

What to expect in each field:

- **Scores are `null` before a game starts**, `period` is `null` until play begins, and `clock` is filled only while a game is in progress. `winner` is set once a game is final.
- **Odds are `null` when ESPN shows no line for the game.** ESPN posts odds for upcoming and live games and usually drops them after the game ends, so past dates mostly give scores without odds. Lower leagues and far-future games often have none. Use `onlyWithOdds` to skip those.
- **Odds come from the sportsbook ESPN names in `odds.provider`**, one provider per game. This is not a multi-book comparison.
- `drawMoneyline` is filled for soccer only.
- `season` is ESPN's season number (the 2026-27 NBA season is 2027). `week` is filled for the NFL and college football.

Empty input runs the built-in example: the current scoreboard of the first of NFL, NBA, NHL, MLB, Premier League, college football or MLS that has games, at most 5 rows. The input prefill (`nfl` and `nba`, 10 games) runs the same way with a limit of 10.

### Pricing

Pay per event: **$1.00 per 1,000 games** ($0.001 per game), charged for each game row written to the dataset. Platform usage is included in that price; you pay nothing else for this Actor. Apify subscribers on the Silver plan pay 15% less and Gold 30% less.

Worked example: a full NFL week (about 14 games) is $0.014. A whole 380-game Premier League season is $0.38, and a full 1,230-game NBA regular season is $1.23. Pulling today's NBA, NHL and MLB boards every morning is roughly 15 games, about $0.45 a month.

Set `maxGames` or a maximum total charge on the run and the Actor stops cleanly when it is reached; everything collected up to that point is kept.

### Limits

- **Data is as fresh as ESPN's scoreboard,** which updates live scores within seconds to a minute. Schedule the Actor to poll; it is not a push feed.
- **One request per league per day.** ESPN's scoreboard no longer accepts date ranges in one call, so the Actor asks for each day separately. A 30-day range for 3 leagues is 90 requests, usually under a minute. Ranges are capped at 92 days.
- **Odds are limited to what ESPN publishes:** one provider, with spread, total and moneylines. No player props, no alternate lines, no line history beyond the opening line.
- **College football returns FBS games, college basketball Division I games.** Smaller divisions are not included.
- ESPN can change its JSON. If a field disappears, rows still come back with it `null` and the run does not fail.

### Use with Python

```python
## pip install apify-client
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("datagleaner/sports-scores-odds").call(
    run_input={"leagues": ["nfl"], "onlyWithOdds": True, "maxGames": 20}
)
for g in client.dataset(run["defaultDatasetId"]).iterate_items():
    o = g["odds"]
    print(g["shortName"], g["startTime"], o["details"], "total", o["overUnder"])
```

This run returns at most 20 games, so it costs at most $0.02.

### Use with JavaScript / Node.js

```js
// npm install apify-client
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('datagleaner/sports-scores-odds').call({
    leagues: ['nba'],
    dateFrom: '2026-10-20',
    dateTo: '2026-10-21',
    maxGames: 20,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const g of items) console.log(g.shortName, g.status, g.awayTeam.score, g.homeTeam.score);
```

### Use it from n8n, Make, Zapier or an AI agent

Actor ID: `datagleaner/sports-scores-odds`

Minimal input:

```
{"leagues": ["nfl", "nba"], "maxGames": 20}
```

Each tool below runs this Actor with your own Apify API token.

- **n8n:** add the **Apify** node (`@apify/n8n-nodes-apify`). On n8n Cloud you install it from the community node registry. Choose **Run an Actor and get dataset**, set Actor to `datagleaner/sports-scores-odds` and paste the input above.
- **Make:** use the Apify app's **Run an Actor** module, then **Get Dataset Items** to read the results. **Watch Actor Runs** can trigger a scenario when a run finishes.
- **Zapier:** use the Apify action **Run Actor**, then the search **Fetch dataset items**. The trigger **Finished Actor run** starts a Zap when a run ends.
- **AI agents (MCP):** connect to `https://mcp.apify.com?tools=datagleaner/sports-scores-odds`. Without a token, an agent can still find the Actor with the `search-actors` tool, but running it needs your Apify account. In Claude Code:

  ```
    claude mcp add --transport http apify "https://mcp.apify.com?tools=datagleaner/sports-scores-odds"
  ```

  Then run `/mcp` to sign in to Apify in your browser. Or pass a token instead:

  ```
    claude mcp add --transport http apify "https://mcp.apify.com?tools=datagleaner/sports-scores-odds" --header "Authorization: Bearer YOUR_APIFY_TOKEN"
  ```

  Claude Desktop, Cursor and other clients that use an `mcpServers` config can run the server locally:

  ```
    {
      "mcpServers": {
        "actors-mcp-server": {
          "command": "npx",
          "args": ["-y", "@apify/actors-mcp-server"],
          "env": { "APIFY_TOKEN": "YOUR_APIFY_TOKEN" }
        }
      }
    }
  ```

  Then ask in plain language, for example: "Use the sports scores and odds Actor to get this week's NFL games with spread, total and moneylines, and give me a table of matchup, kickoff time, favorite and over/under."
- **LangChain (Python):**

```python
## pip install langchain-apify, then set APIFY_TOKEN in your environment
import json
from langchain_apify import ApifyActorsTool
tool = ApifyActorsTool("datagleaner/sports-scores-odds")
result = tool.invoke({"run_input": json.loads('{"leagues": ["nfl"], "maxGames": 20}')})
```

### FAQ

**Is this a sports odds API?** It works as one: call it through the Apify API, the clients above or MCP and get JSON back. It needs no ESPN account and no sportsbook key, only an Apify account. The odds are the lines ESPN publishes from one sportsbook, not a feed from many books.

**How do I get NFL odds for this week?** Set `leagues` to `["nfl"]`, leave the dates empty and turn on `onlyWithOdds`. You get each game's spread, total and moneylines, plus the opening line in `odds.open`.

**How do I get NBA scores for a date range?** Set `leagues` to `["nba"]`, `dateFrom` and `dateTo`. Past games come back as `final` with scores and period scores in `linescores`. Odds are mostly empty for finished games.

**Why is `odds` null?** ESPN shows no line for that game: it is finished, too far ahead, or in a league without odds. Upcoming games in the major leagues almost always have one.

**What does a negative spread mean?** `spread` is from the home team's side. -3.0 means the home team is favored by 3 points. `details` repeats it in ESPN's wording, such as "CHI -3", and `favorite` names the favored team.

**Can I track line movement?** `odds.open` against the current `odds` shows the move since the line opened. For more, schedule the Actor (hourly or daily) and compare runs by `eventId`.

**How do I get live scores?** Run the Actor on a schedule for today's date. Games in progress show `status: "in progress"`, `period`, `clock` and the running score.

**Is it legal to use?** The Actor reads public data that ESPN serves without a login. You are responsible for how you use it, including ESPN's terms for any redistribution and the gambling laws where you live.

### Responsible use

The data is public and provided for analysis, research and display. It is not betting advice, and odds can change or be wrong; check a sportsbook before you rely on a line. If gambling is a problem for you or someone you know, call 1-800-GAMBLER in the US. This Actor is not affiliated with or endorsed by ESPN or any league or sportsbook, and the names are used only to say where the data comes from.

# Actor input Schema

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

One or more leagues. Each league and day is one request to ESPN's scoreboard. Soccer leagues use ESPN's codes (eng.1 is the Premier League).

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

First day, YYYY-MM-DD, in ESPN's schedule days (US Eastern). Leave both dates empty for the current scoreboard: today's games, or for the NFL and college football the whole current week. Past days give finished games with final scores; future days give the schedule with odds where posted.

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

Last day, YYYY-MM-DD. Empty means the same day as 'From date'. A range is read one day per request, up to 92 days.

## `onlyWithOdds` (type: `boolean`):

Return only games that have odds posted. ESPN posts odds for upcoming and live games; finished games usually carry none.

## `maxGames` (type: `integer`):

Stop after this many game rows in total (across all leagues). It is also your cost cap: each row is one billable game.

## `requestDelaySeconds` (type: `number`):

Polite pause before each request to ESPN. Raise it if you pull a long date range.

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

Optional. ESPN answers Apify's servers without a proxy, so leave this off unless you need a specific egress country.

## Actor input object example

```json
{
  "leagues": [
    "nfl",
    "nba"
  ],
  "onlyWithOdds": false,
  "maxGames": 10,
  "requestDelaySeconds": 0.2
}
```

# Actor output Schema

## `games` (type: `string`):

No description

## `results` (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"
    ],
    "maxGames": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("datagleaner/sports-scores-odds").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",
    ],
    "maxGames": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("datagleaner/sports-scores-odds").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"
  ],
  "maxGames": 10
}' |
apify call datagleaner/sports-scores-odds --silent --output-dataset

```

## MCP server setup

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

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/DbgaGOa6jsGh5logn/builds/fnvgM0JN2ojoTfGfW/openapi.json
