espn_odds_scraper
Scrape historical and live MLB odds from ESPN's public (undocumented) API. No API key, no Selenium — plain JSON requests.
Successor to mlb_odds_scraper (OddsPortal/Selenium based). ESPN carries per-book odds (DraftKings, FanDuel, Caesars, MGM, Bet365, ...; older seasons carry BOVADA, 5Dimes, etc.), moneyline + run line + total in a single request per game, and timestamped line-movement history on its consensus feed.
Coverage: solid from ~2015 onward. Earlier seasons exist but are degraded (moneylines often missing).
Install
pip install espn_odds_scraper
Usage
from espn_odds_scraper import scrape_espn_mlb, scrape_espn_mlb_years
# One day, every book — one row per game x sportsbook
df = scrape_espn_mlb("2023-07-14")
# Date range, only certain books
df = scrape_espn_mlb("2023-07-01", "2023-07-31", providers=["DraftKings", "FanDuel"])
# With full timestamped line movement (opt-in, ~3 extra requests per game)
odds, movement = scrape_espn_mlb("2023-07-14", include_history=True)
# Whole seasons
df = scrape_espn_mlb_years(2018, 2024)
Odds DataFrame columns
game_id, game_datetime (UTC), status, completed, home_team_abbr, away_team_abbr, home_team_name, away_team_name, home_team_espn_id, away_team_espn_id, home_score, away_score, provider_id, provider, home_ml, away_ml, spread (home line), home_spread_odds, away_spread_odds, total, over_odds, under_odds, open_* (8 cols), close_* (8 cols), moneyline_winner, spread_winner
For completed games, per-book odds are the lines frozen at game time — effectively closing lines. In-game "Live Odds" feeds are dropped by default (exclude_live=False to keep them).
Opening / closing lines & line movement
ESPN's data comes in two eras:
- 2024+ (ESPN BET / DraftKings era): each book carries real
open_*andclose_*snapshots (moneyline, spread + prices, total + prices) directly in the odds row — no extra requests. Fewer books, though (often just one). - ≤2023 (multi-book era):
open_*/close_*are empty (ESPN stored junk there), but full timestamped line movement exists on the consensus feed:
from espn_odds_scraper import fetch_line_history, get_open_close
movement = fetch_line_history("401472391") # timestamped rows per market
oc = get_open_close(movement) # one row per market: open_* and close_*
Movement rows: game_id, market (moneyline/spread/total), line_date (UTC), away_odds, home_odds, over_odds, under_odds, line. First row per market is the opener, last is the closer. ESPN dropped this feed after the 2023 season.
Drop-in compatibility with mlb_odds_scraper
from espn_odds_scraper import to_legacy_format, clean_game_data
legacy = to_legacy_format(df) # game_date, game_datetime, home_team/away_team
# (statsapi ids), home_odds/away_odds, scores, abbrs
merged = clean_game_data(cleaned_schedule, legacy) # same merge helper as before
Request footprint
- 1 request per day (schedule + scores)
- 1 request per game (all books, all markets)
- optional: 3 requests per game (line movement)
A full season is roughly 2,600 requests without history. Requests run through a thread pool (max_workers=8 by default). Be polite; this is an undocumented API.
License
MIT
Metadata
Release files for espn-odds-scraper 0.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| espn_odds_scraper-0.2.2.tar.gz | 15.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| espn_odds_scraper-0.2.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 31.9 kB
Release files / espn_odds_scraper-0.2.2.tar.gz
| Download URL | espn_odds_scraper-0.2.2.tar.gz |
|---|---|
| Size | 15.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ea3cc867f3f0b7b834d0e9196a21961837082f54c9003e900defb41274b26f12
|
|
BLAKE2b-256 checksum How to use checksums |
9bb8c0645b17d13c29768681f350ee4cf8760dd2058edfc73ed4bee6dff8751e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.11.9
|
Release files / espn_odds_scraper-0.2.2-py3-none-any.whl
| Download URL | espn_odds_scraper-0.2.2-py3-none-any.whl |
|---|---|
| Size | 16.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f80eac03c4022dcea288d8af857dc67b78b8b5065c7eb0fda75f22242cb4954f
|
|
BLAKE2b-256 checksum How to use checksums |
37f4f453ceec098ae8b4321a03bc469d5e162cb70d6e7cb8c8f3dba41aa240b2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.11.9
|