# NBA, NFL, MLB & NHL Odds: Historical & Closing Lines (`sports-odds-lab/nba-nfl-mlb-nhl-odds`) Actor

NBA, NFL, MLB and NHL odds from up to 42 bookmakers incl. DraftKings, FanDuel, BetMGM and Fanatics: moneyline, spread, total, 3-way. Opening and closing lines, no-vig consensus, line movement. Recent games or full seasons back to 2009, scores by period, team stats.

- **URL**: https://apify.com/sports-odds-lab/nba-nfl-mlb-nhl-odds.md
- **Developed by:** [Sports Odds Lab](https://apify.com/sports-odds-lab) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 83.3% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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

## NBA, NFL, MLB & NHL Odds: Historical & Closing Lines

> 🎁 **Free until 8 October 2026.** Press **Start** — the prefilled input returns 30 games with odds in under a minute.

![Sample output: NBA 2024/25 with fair moneylines, spread and total at the open and the close](https://api.apify.com/v2/key-value-stores/CEtWcytR8Vm5hiMr1/records/preview-us.png?signature=1SBfeiOPUVARJsA7H6Gvy)

Get **NBA, NFL, MLB and NHL odds — and every other basketball, American football, ice hockey and baseball league** — with the **opening and closing line of up to 42 bookmakers**, including **DraftKings, FanDuel, BetMGM, Fanatics** and bet365: **moneyline, spread (point spread, run line, puck line), total and 3-way**, a **no-vig market consensus**, the **main lines at the open and at the close**, **line movement**, final and period-by-period **scores** and **team box-score statistics**. One clean row per game, ready for a spreadsheet, a database or a model.

**Two modes:**

- **Recent games** — every league of the chosen sports, from 7 days back to 7 days ahead (upcoming games with current prices)
- **Full seasons** — complete seasons of the leagues you choose, with **odds history back to 2009**: regular season, play-offs, play-in, wild card, bowls

Most odds scrapers give you today's lines from a handful of US books. This Actor gives you the **history** — opening and closing lines season after season — the data you need to build and backtest betting models or to measure closing line value.

### What you get for each game

- **Game**: start time (UTC), sport, country, league, stage and **season type** (regular / postseason / preseason / all-star), round, home and away team, Flashscore IDs and link
- **Result**: status, final score (overtime included; a hockey shoot-out counts as one goal for the winner, as in the official result), **regulation score**, score after overtime, shoot-out, **periods** (quarters, periods or innings), overtime / extra-innings flag, winner, regulation result (for 3-way bets)
- **Odds per bookmaker** — opening price and latest price; once a game has started the latest price is the **closing line**:
  - **Moneyline** (including overtime) with the bookmaker margin
  - **Spread** — each bookmaker's own main line at the close, or every alternate line
  - **Total** — each bookmaker's own main line at the close, or every alternate line
  - **3-way** on regulation time *(optional)*
- **Market consensus** (median across bookmaker brands, margin removed):
  - fair moneyline odds and win probability at the open and at the close, **line movement** in percentage points
  - the **main spread and total at the open and at the close** (voted across bookmakers) with their fair prices
  - best available prices, median moneyline margin
- **Team statistics** *(where available)*: field goals, 3-pointers, rebounds, assists, turnovers; shots, power plays, faceoffs, hits; hits, errors, home runs; yards, first downs, turnovers …
- **Odds format**: decimal or **American** (`-110`, `+150`)

### Historical odds: full seasons back to 2009

| League and season | Bookmakers per game (moneyline) |
|---|---|
| NBA 2009/10 – 2012/13 | 6 |
| NFL 2011/12 · NHL 2012/13 | 8–9 |
| MLB 2014 | 7 |
| NBA · NFL · NHL 2019/20 · MLB 2019 | 9–11 |
| NBA · NFL · NHL 2024/25 · MLB 2024 | 17–22 |
| Current season (e.g. MLB 2026) | 30+ listings |

Spreads and totals are quoted by fewer books than the moneyline (roughly half to two thirds as many). A full season comes complete: e.g. **2,473 MLB games in 2024**, **1,386 NBA games in 2024/25** (preseason and all-star games are skipped unless you ask for them).

**About line-moving books:** US books move the line and keep the price at -110. Only the line still quoted at the close counts as that book's closing line; the opening main line is the one the market started from.

### Leagues

Everything Flashscore covers for these four sports — the **NBA, WNBA, NCAA, EuroLeague** and hundreds of basketball leagues; the **NFL, NCAA, CFL**; the **NHL, KHL, AHL, SHL, Liiga, DEL**; **MLB, NPB, KBO, CPBL** and more. In *Full seasons* mode use the short names `NBA`, `NFL`, `MLB`, `NHL`, `WNBA`, `NCAAB`, `NCAAF`, `EuroLeague`, `KHL`, `AHL`, `CFL`, `NPB`, `KBO`, or `Sport: Country: League` as shown on Flashscore (`Basketball: Spain: ACB`, `Hockey: Sweden: SHL`), or paste the league's Flashscore URL.

### Use cases

- **Build and backtest models** — closing-line probabilities are the most efficient price the market produces
- **Closing Line Value (CLV)** — compare the price you bet with the consensus close
- **Line movement** — find games where the spread or total moved between open and close
- **Line shopping history** — see which book offered the best price, game after game
- **Your own odds database** — schedule a daily run of recent games and keep appending

### How to use it

1. Choose *Recent games* (sports, days back/ahead) or *Full seasons* (leagues and seasons).
2. Pick the markets and the odds format.
3. Click **Start**. 30 recent games take about half a minute; a full NBA season (1,314 games with the play-offs) about 18 minutes. For many leagues and seasons, raise the run timeout (the default is 6 hours).
4. Download the results as JSON, CSV or Excel, or read them through the Apify API.

### Ready-made examples

One click, preconfigured — open, press **Start**, adjust if you like:

- [NBA odds history: moneyline, spread and total](https://apify.com/sports-odds-lab/nba-nfl-mlb-nhl-odds/examples/nba-odds-history)
- [NFL closing lines](https://apify.com/sports-odds-lab/nba-nfl-mlb-nhl-odds/examples/nfl-closing-lines-history)
- [MLB odds history](https://apify.com/sports-odds-lab/nba-nfl-mlb-nhl-odds/examples/mlb-odds-history)
- [NHL odds history](https://apify.com/sports-odds-lab/nba-nfl-mlb-nhl-odds/examples/nhl-odds-history)
- [Tonight's NBA, NFL, MLB and NHL odds](https://apify.com/sports-odds-lab/nba-nfl-mlb-nhl-odds/examples/tonights-odds-nba-nfl-mlb-nhl)
- [College football (NCAAF) odds history](https://apify.com/sports-odds-lab/nba-nfl-mlb-nhl-odds/examples/ncaa-football-odds-history)

#### Input example — full seasons

```json
{
  "mode": "seasons",
  "leagues": ["NBA", "NFL", "NHL", "MLB"],
  "seasons": ["2024-2025", "2024"],
  "markets": ["moneyline", "spread", "total"],
  "oddsFormat": "american"
}
```

Seasons follow the league's own format: `2024-2025` for the NBA and NHL, `2024` for MLB and other calendar-year leagues; for the NFL both `2024` and `2024-2025` work. Leave `seasons` empty and set `lastSeasons` to get the current season plus the ones before it.

#### Input example — recent games

```json
{
  "mode": "recent",
  "sports": ["basketball", "baseball"],
  "competitions": ["USA: NBA", "USA: MLB"],
  "daysBack": 1,
  "daysAhead": 1,
  "oddsFormat": "american"
}
```

#### Output example (shortened, American odds)

```json
{
  "matchId": "YasLoKTi",
  "startTime": "2025-06-23T00:00:00Z",
  "sport": "basketball",
  "competition": "NBA - Play Offs",
  "season": "2024/2025",
  "seasonType": "postseason",
  "round": "Final",
  "homeTeam": "Oklahoma City Thunder",
  "awayTeam": "Indiana Pacers",
  "status": "finished",
  "score": "103-91",
  "periods": [[25, 22], [22, 26], [34, 20], [22, 23]],
  "winner": "home",
  "consensus": {
    "booksMoneyline": 25,
    "probHomeOpening": 0.7407,
    "probHomeLast": 0.6938,
    "fairHomeOdds": -227,
    "fairAwayOdds": 227,
    "moveHomePts": -4.69,
    "spreadLine": -6.5,
    "spreadLineOpening": -8.5,
    "fairSpreadHomeOdds": -105,
    "totalLine": 215.5,
    "totalLineOpening": 214.5,
    "fairOverOdds": 100
  },
  "odds": {
    "moneyline": [{"bookmaker": "BetMGM.us", "opening1": -385, "opening2": 290, "last1": -278, "last2": 225, "marginPct": 4.3}],
    "spread": [{"bookmaker": "BetMGM.us", "line": -6.5, "openingHome": -154, "openingAway": 125, "lastHome": -110, "lastAway": -110}],
    "total": [{"bookmaker": "BetMGM.us", "line": 215.5, "openingOver": -110, "openingUnder": -110, "lastOver": -110, "lastUnder": -110}]
  },
  "stats": {
    "fieldGoalsAttempts": {"home": 87, "away": 70},
    "fieldGoalsMade": {"home": 35, "away": 29}
  }
}
```

### Pricing

🏀 **Free until 8 October 2026** — during the launch period you only pay Apify's platform usage, typically well under $0.01 per 100 games.

**From 9 October 2026 you pay per game saved — platform usage included**, nothing else:

| Apify plan | Price per 1,000 games |
|---|---|
| Free | $5.00 |
| Starter | $4.50 |
| Scale | $4.00 |
| Business and higher | $3.50 |

💡 **On Apify's free plan the monthly $5 platform credit covers about 1,000 games** — enough to try the data properly before paying anything.

Every game comes with the odds of all bookmakers and markets you selected, the consensus and the statistics, at no extra cost. Nothing is charged for games you filter out: **Skip games without odds** is on by default. Set a spending limit on the run if you want a hard cap — the Actor stops as soon as the limit is reached.

### FAQ

**What is the "closing line"?** The last price before the game starts. For finished and live games the `last…` fields are the closing odds; for scheduled games the current ones.

**Do moneyline, spread and total include overtime?** Yes — they are quoted including overtime and extra innings, the way US books settle them. The 3-way market is on regulation time (`regulationResult`).

**How is the consensus calculated?** Each bookmaker's margin is removed proportionally, then the median is taken across bookmaker brands (each brand once, via its lowest-margin listing). The main spread and total are the lines most bookmakers quote closest to 50/50.

**How far back can I go?** In *Recent games* mode 7 days back and 7 ahead. In *Full seasons* mode every season Flashscore lists — odds go back to 2009 (fewer bookmakers in older seasons, see the table above). US books such as DraftKings and FanDuel appear in recent seasons.

**Which time zone?** All timestamps are UTC.

**Where does the data come from?** From publicly available game and odds information shown on Flashscore. This Actor is not affiliated with Flashscore, the leagues or any bookmaker.

### More from Sports Odds Lab

- ⚽ [Football Odds Scraper](https://apify.com/sports-odds-lab/football-odds-results) — 1,000+ competitions, 1X2, over/under, BTTS and Asian handicap, seasons back to 2005
- 🎾 [Tennis Scraper: Live Scores, Results & Odds](https://apify.com/sports-odds-lab/tennis-odds-results) — every ATP, WTA, Challenger and ITF match: live scores, rankings, odds from 40+ bookmakers back to 2009
- 📊 [Polymarket & Kalshi Scraper](https://apify.com/sports-odds-lab/polymarket-kalshi-odds) — prediction market odds, price history and results in one table, full Kalshi archive since 2021

⭐ **Did this Actor save you time?** A short review on this page helps other bettors and analysts find it — and tells us what to build next.

### Changelog

- **0.1** — first release (free launch period): basketball, American football, ice hockey and baseball; moneyline, spread, total and 3-way from up to 42 bookmakers, opening and closing; no-vig consensus, main lines, line movement; full seasons back to 2009; periods, season types, team statistics; decimal or American odds.

# Actor input Schema

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

Recent games: every league of the chosen sports from up to 7 days back to 7 days ahead (upcoming games with current odds). Full seasons: complete seasons of the leagues you list below, odds history back to 2009 — add the leagues in the 'Full seasons' section.

## `statuses` (type: `array`):

Finished includes games decided in overtime, extra innings or a shoot-out.

## `seasonTypes` (type: `array`):

Regular season, postseason (play-offs, play-in, wild card, bowls, Final Four), preseason and all-star games.

## `sports` (type: `array`):

Every league of these sports: NBA, WNBA, NCAA, EuroLeague …; NFL, NCAA, CFL …; NHL, KHL, AHL, SHL …; MLB, NPB, KBO …

## `daysBack` (type: `integer`):

How many past days to include (0 = today only). Up to 7.

## `daysAhead` (type: `integer`):

How many upcoming days to include. Up to 7. Upcoming games carry the current prices instead of closing lines.

## `countries` (type: `array`):

Optional. Country names as shown on Flashscore, e.g. USA, Canada, Spain, Japan, Europe (EuroLeague). Leave empty for every country.

## `competitions` (type: `array`):

Optional. 'Country: Competition' as shown on Flashscore, e.g. 'USA: NBA', 'USA: NFL', 'USA: NCAA', 'Europe: Euroleague'. Stages (play-offs, preseason) are included automatically.

## `includeWomen` (type: `boolean`):

WNBA and other women's competitions.

## `includeYouth` (type: `boolean`):

U18–U23, junior and academy competitions.

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

Short names NBA, NFL, MLB, NHL, WNBA, NCAAB, NCAAF, EuroLeague, KHL, AHL, CFL, NPB, KBO — or 'Sport: Country: League' as shown on Flashscore (e.g. 'Basketball: Spain: ACB', 'Hockey: Sweden: SHL'), or the league's Flashscore URL.

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

Optional. 2024-2025 for NBA/NHL/NFL-style seasons (for the NFL, 2024 also works), 2024 for MLB and other calendar-year leagues. Leave empty to use 'Last seasons'.

## `lastSeasons` (type: `integer`):

Used when Seasons is empty: the current season (games played so far) plus this many minus one before it; seasons that have not started are skipped.

## `markets` (type: `array`):

Moneyline, spread and total include overtime / extra innings (as US books settle them). 3-way is on regulation time. The moneyline is always included — it shows which bookmakers priced the game.

## `spreadLines` (type: `string`):

The consensus always reports the market's main line at the open and at the close.

## `totalLines` (type: `string`):

The consensus always reports the market's main line at the open and at the close.

## `oddsFormat` (type: `string`):

Format of every price in the output. Probabilities are always 0–1.

## `bookmakers` (type: `array`):

Optional. Names or parts of names, e.g. DraftKings, FanDuel, BetMGM, bet365. Leave empty for all available (up to 42).

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

Opening and latest (closing) odds per bookmaker plus the no-vig consensus.

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

Do not save (and do not pay for) games that no bookmaker priced — mostly minor and youth leagues.

## `includeStats` (type: `boolean`):

Box-score team statistics where available: field goals, rebounds, turnovers; shots, power plays, faceoffs; hits, errors, home runs; yards, turnovers …

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

Stop after saving this many games (0 = no limit). A full NBA season is ~1,300 games, MLB ~2,500.

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

Advanced. Higher is faster; the default is safe.

## Actor input object example

```json
{
  "mode": "recent",
  "statuses": [
    "finished"
  ],
  "seasonTypes": [
    "regular",
    "postseason"
  ],
  "sports": [
    "basketball",
    "americanFootball",
    "hockey",
    "baseball"
  ],
  "daysBack": 1,
  "daysAhead": 0,
  "includeWomen": true,
  "includeYouth": true,
  "leagues": [
    "NBA"
  ],
  "seasons": [
    "2024-2025"
  ],
  "lastSeasons": 1,
  "markets": [
    "moneyline",
    "spread",
    "total"
  ],
  "spreadLines": "main",
  "totalLines": "main",
  "oddsFormat": "american",
  "includeOdds": true,
  "onlyWithOdds": true,
  "includeStats": true,
  "maxGames": 30,
  "concurrency": 16
}
```

# Actor output Schema

## `overview` (type: `string`):

One row per game: teams, score, main lines and the no-vig consensus.

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

Full records including the odds of every bookmaker, periods and team statistics.

# 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": "recent",
    "statuses": [
        "finished"
    ],
    "sports": [
        "basketball",
        "americanFootball",
        "hockey",
        "baseball"
    ],
    "daysBack": 1,
    "daysAhead": 0,
    "leagues": [
        "NBA"
    ],
    "seasons": [
        "2024-2025"
    ],
    "markets": [
        "moneyline",
        "spread",
        "total"
    ],
    "oddsFormat": "american",
    "maxGames": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("sports-odds-lab/nba-nfl-mlb-nhl-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 = {
    "mode": "recent",
    "statuses": ["finished"],
    "sports": [
        "basketball",
        "americanFootball",
        "hockey",
        "baseball",
    ],
    "daysBack": 1,
    "daysAhead": 0,
    "leagues": ["NBA"],
    "seasons": ["2024-2025"],
    "markets": [
        "moneyline",
        "spread",
        "total",
    ],
    "oddsFormat": "american",
    "maxGames": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("sports-odds-lab/nba-nfl-mlb-nhl-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 '{
  "mode": "recent",
  "statuses": [
    "finished"
  ],
  "sports": [
    "basketball",
    "americanFootball",
    "hockey",
    "baseball"
  ],
  "daysBack": 1,
  "daysAhead": 0,
  "leagues": [
    "NBA"
  ],
  "seasons": [
    "2024-2025"
  ],
  "markets": [
    "moneyline",
    "spread",
    "total"
  ],
  "oddsFormat": "american",
  "maxGames": 30
}' |
apify call sports-odds-lab/nba-nfl-mlb-nhl-odds --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sports-odds-lab/nba-nfl-mlb-nhl-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/c8kcPz508SPc70Hxc/builds/cH9CdfpJRYeChFqRU/openapi.json
