There are four major sources of prediction market data for sports events. Each has a different API, different authentication, different data format, and different strengths. This guide covers all of them with working Python code.
1. Polymarket CLOB API
Polymarket runs a Central Limit Order Book (CLOB) on Polygon. You can read orderbooks, place trades, and stream real-time prices.
Official docs: docs.polymarket.com Python client: py-clob-client Authentication: API key + secret + passphrase + Polygon private key Rate limits: ~100 requests/second (generous) Data format: JSON Fee: ~2% on fills
Best for: Live trading, real-time orderbook data, sports moneylines
from py_clob_client.client import ClobClient
from py_clob_client.clob_types import ApiCreds
import os
client = ClobClient(
"https://clob.polymarket.com",
key=os.environ["POLY_PRIVATE_KEY"],
chain_id=137,
creds=ApiCreds(
api_key=os.environ["POLY_API_KEY"],
api_secret=os.environ["POLY_API_SECRET"],
api_passphrase=os.environ["POLY_PASSPHRASE"],
),
)
# Read orderbook
book = client.get_order_book("TOKEN_ID_HERE")
best_bid = float(book.bids[0].price) if book.bids else 0
best_ask = float(book.asks[0].price) if book.asks else 1
Market discovery uses the Gamma API (separate from CLOB):
import requests
markets = requests.get(
"https://gamma-api.polymarket.com/markets",
params={"tag": "sports", "active": True, "limit": 50}
).json()
WebSocket streaming for real-time prices:
import websockets, json
async def stream(token_ids):
async with websockets.connect("wss://ws-subscriptions-clob.polymarket.com/ws/market") as ws:
await ws.send(json.dumps({"type": "subscribe", "markets": token_ids}))
async for msg in ws:
print(json.loads(msg))
Strengths: Real-time data, full orderbook depth, direct execution Weaknesses: Thin liquidity on esports/minor sports, 10-30s price lag after score changes
Full tutorial: Polymarket API Python Tutorial
2. Kalshi REST API
Kalshi is a CFTC-regulated event contract exchange. They offer sports markets alongside political, economic, and weather events.
Official docs: trading-api.readme.io Authentication: Email + password → JWT token Rate limits: 10 requests/second Data format: JSON Fee: Variable (typically 7-10% of profit on winning trades)
Best for: Regulated event contracts, spread/total markets, US-regulated trading
import requests
# Login
resp = requests.post("https://trading-api.kalshi.com/trade-api/v2/login", json={
"email": "your@email.com",
"password": "your_password"
})
token = resp.json()["token"]
headers = {"Authorization": f"Bearer {token}"}
# Get markets
markets = requests.get(
"https://trading-api.kalshi.com/trade-api/v2/markets",
headers=headers,
params={"series_ticker": "KXNBAGAME", "status": "open"}
).json()
# Get orderbook
ticker = "KXNBAGAME-26APR21-LAL-BOS"
book = requests.get(
f"https://trading-api.kalshi.com/trade-api/v2/markets/{ticker}/orderbook",
headers=headers
).json()
Strengths: Regulated (CFTC), spread/total markets available, clean REST API Weaknesses: Lower liquidity than Polymarket, higher fees, fewer sports
3. ESPN Scoreboard API (Free Sports Data)
ESPN has an undocumented API that powers their website. Free, no authentication, covers every major sport.
Docs: None (undocumented) Authentication: None required Rate limits: ~1 request/second per endpoint Data format: JSON Fee: Free
Best for: Live scores, game state, win probability estimates, historical data collection
import requests
# Today's NBA games
data = requests.get(
"https://site.api.espn.com/apis/site/v2/sports/basketball/nba/scoreboard"
).json()
for event in data["events"]:
game = event["competitions"][0]
home = game["competitors"][0]
away = game["competitors"][1]
print(f"{away['team']['abbreviation']} @ {home['team']['abbreviation']}: "
f"{away['score']}-{home['score']}")
Supported sports:
| Sport | Endpoint |
|-------|----------|
| NBA | basketball/nba |
| NFL | football/nfl |
| NCAAMB | basketball/mens-college-basketball |
| NHL | hockey/nhl |
| MLB | baseball/mlb |
| CFB | football/college-football |
| Soccer | soccer/eng.1 (EPL), soccer/esp.1 (La Liga) |
Strengths: Free, comprehensive, includes ESPN win probability, all major sports Weaknesses: Undocumented (could change), 10-15s latency, no guaranteed uptime
Full tutorial: ESPN API Python Tutorial
4. The Odds API (Sportsbook Aggregator)
The Odds API aggregates real-time odds from DraftKings, FanDuel, BetMGM, Caesars, and 15+ other sportsbooks.
Official docs: the-odds-api.com/liveapi Authentication: API key (free tier: 500 requests/month) Rate limits: Per-plan (free: 500/month, $5: 100K/month) Data format: JSON Fee: $0-$5/month for API access
Best for: Cross-venue price comparison, devigging sportsbook lines, CLV tracking
import requests
API_KEY = "your_key_here"
resp = requests.get(
"https://api.the-odds-api.com/v4/sports/basketball_nba/odds",
params={
"apiKey": API_KEY,
"regions": "us",
"markets": "h2h",
"oddsFormat": "american",
"bookmakers": "draftkings,fanduel,betmgm",
}
).json()
for event in resp:
print(f"{event['away_team']} @ {event['home_team']}")
for bm in event["bookmakers"]:
for market in bm["markets"]:
for outcome in market["outcomes"]:
print(f" {bm['key']}: {outcome['name']} {outcome['price']}")
Devigging (removing the bookmaker's margin):
def american_to_implied(odds):
if odds > 0:
return 100.0 / (odds + 100.0)
return abs(odds) / (abs(odds) + 100.0)
def devig(home_odds, away_odds):
home_raw = american_to_implied(home_odds)
away_raw = american_to_implied(away_odds)
total = home_raw + away_raw # >1.0 because of vig
return home_raw / total, away_raw / total # true probabilities
Strengths: Aggregates 15+ sportsbooks, clean format, affordable Weaknesses: No execution (read-only), 30-60s latency on live odds
Full guide: Multi-Venue Edge Detection
Comparison Table
| Feature | Polymarket | Kalshi | ESPN | The Odds API |
|---|---|---|---|---|
| Auth | API key + wallet | Email + JWT | None | API key |
| Execution | Yes | Yes | No | No |
| Real-time | WebSocket | Polling | Polling | Polling |
| Free tier | Full access | Full access | Unlimited | 500 req/mo |
| Sports | 9+ | 6 | 7+ | 6 |
| Best for | Trading | Regulated trading | Data/scores | Odds comparison |
| Python lib | py-clob-client | requests | requests | requests |
| Latency | <1s (WS) | 1-2s | 10-15s | 30-60s |
Building a Multi-Source Pipeline
The most powerful approach combines all four:
- ESPN for live scores and game state (free, comprehensive)
- Your ML model trained on ESPN data to predict fair win probability
- Polymarket for real-time market prices and execution
- The Odds API for sportsbook prices as confirmation signals
When your model disagrees with Polymarket AND DraftKings/FanDuel agree with your model, you have a high-confidence edge. When your model disagrees with everyone, you're probably wrong.
We built this exact pipeline. It runs on a $7/month VPS, polls ESPN every 5 seconds, receives Polymarket prices via WebSocket, and checks sportsbook odds every 2 minutes. The complete system is taught step-by-step in our course.
This guide is maintained by ZenHodl. Last updated April 2026. API endpoints and authentication methods may change — check official documentation for the latest.