Developer Tutorial

Sports Betting API in Python

A complete tutorial — from installation to fetching live NBA odds to streaming line changes as they happen. All examples use the SharpAPI Python SDK and work on the free tier (12 req/min, no card required).

By theFounder·SharpAPI

To get real-time sports betting odds in Python, install the SharpAPI SDK with pip install sharpapi, authenticate with an API key, and call client.odds.list(sport="basketball_nba"). You get structured JSON with moneylines, spreads, totals, and player props from 32+ sportsbooks. For real-time updates, use SSE streaming via client.stream.odds() — delta updates arrive the instant lines move.

1. Installation

Install the SDK and python-dotenv for env var management:

pip install sharpapi python-dotenv

Create a .env file with your API key:

SHARPAPI_KEY=your_api_key_here

Get your free API key at sharpapi.io/sign-up — no credit card required.

2. Your First API Call — Fetch NBA Odds

import os
from dotenv import load_dotenv
from sharpapi import SharpAPI

load_dotenv()
client = SharpAPI(api_key=os.environ["SHARPAPI_KEY"])

# Fetch current NBA moneylines from all sportsbooks
odds = client.odds.list(sport="basketball_nba", markets=["h2h"])

for event in odds.data:
    print(f"\n{event.home_team} vs {event.away_team}")
    print(f"Start: {event.commence_time}")
    for book in event.bookmakers:
        market = book.markets[0]
        for outcome in market.outcomes:
            print(f"  {book.title}: {outcome.name} {outcome.price}")

Example output:

Boston Celtics vs Los Angeles Lakers
Start: 2026-04-17T00:30:00Z
  DraftKings: Boston Celtics -160
  FanDuel: Boston Celtics -155
  Pinnacle: Boston Celtics -158
  BetMGM: Boston Celtics -162

3. Fetch Multiple Sports

SPORTS = ["basketball_nba", "americanfootball_nfl", "icehockey_nhl", "baseball_mlb"]

for sport in SPORTS:
    odds = client.odds.list(sport=sport, markets=["h2h", "spreads"])
    print(f"{sport}: {len(odds.data)} events, "
          f"{sum(len(e.bookmakers) for e in odds.data)} book entries")

For parallel fetching (much faster), use the async client:

import asyncio
from sharpapi import AsyncSharpAPI

async def fetch_all_sports():
    async with AsyncSharpAPI(api_key=os.environ["SHARPAPI_KEY"]) as client:
        tasks = [client.odds.list(sport=s, markets=["h2h"]) for s in SPORTS]
        results = await asyncio.gather(*tasks)
    return results

4. Filter for Best Lines

def best_moneyline(event, team_name: str) -> tuple[str, float]:
    """Return (sportsbook, best price) for a given team."""
    best_book, best_price = None, float("-inf")
    for book in event.bookmakers:
        for market in book.markets:
            if market.key == "h2h":
                for outcome in market.outcomes:
                    if outcome.name == team_name and outcome.price > best_price:
                        best_price = outcome.price
                        best_book = book.title
    return best_book, best_price

odds = client.odds.list(sport="basketball_nba", markets=["h2h"])
for event in odds.data:
    home_book, home_price = best_moneyline(event, event.home_team)
    away_book, away_price = best_moneyline(event, event.away_team)
    print(f"{event.home_team} best: {home_price} @ {home_book}")
    print(f"{event.away_team} best: {away_price} @ {away_book}")

5. Detect Arbitrage Opportunities

SharpAPI's built-in arbitrage endpoint (Hobby+ plans) detects cross-book arbs for you:

# Built-in arb detection — Hobby plan and above
arb_opps = client.opportunities.arbitrage(sport="basketball_nba")

for opp in arb_opps.data:
    print(f"Arb: {opp.event}")
    print(f"  Profit: {opp.profit_percent:.2f}%")
    for leg in opp.legs:
        print(f"  {leg.outcome} @ {leg.price} ({leg.sportsbook}) "
              f"— stake {leg.stake_percent:.1f}%")

For a deeper dive on the math and manual detection, see Sports Betting Arbitrage Explained.

6. Stream Live Odds via SSE (Hobby+)

Stop polling. Use SSE streaming for real-time line changes with sub-100ms latency:

def handle_odds_update(data: dict):
    """Called for each live odds change."""
    event_id = data.get("event_id")
    book = data.get("sportsbook")
    for change in data.get("changes", []):
        print(f"[{book}] {event_id}: {change['market']} {change['outcome']} "
              f"{change['old_price']} -> {change['new_price']}")

# Streams indefinitely — reconnects automatically
for update in client.stream.odds(sports=["basketball_nba", "americanfootball_nfl"]):
    handle_odds_update(update)

7. Store Odds in SQLite for Line Movement

import sqlite3
from datetime import datetime

conn = sqlite3.connect("odds_history.db")
conn.execute("""
    CREATE TABLE IF NOT EXISTS odds_log (
        id INTEGER PRIMARY KEY,
        event_id TEXT,
        sportsbook TEXT,
        market TEXT,
        outcome TEXT,
        price REAL,
        fetched_at TEXT
    )
""")

def log_odds(event):
    now = datetime.utcnow().isoformat()
    for book in event.bookmakers:
        for market in book.markets:
            for outcome in market.outcomes:
                conn.execute(
                    "INSERT INTO odds_log VALUES (NULL,?,?,?,?,?,?)",
                    (event.id, book.title, market.key,
                     outcome.name, outcome.price, now),
                )
    conn.commit()

odds = client.odds.list(sport="basketball_nba", markets=["h2h", "spreads"])
for event in odds.data:
    log_odds(event)
print(f"Logged {len(odds.data)} events")

For a full walkthrough on building a line movement tracker, see How to Track Line Movement.

8. Error Handling and Rate Limits

from sharpapi.exceptions import RateLimitError, AuthenticationError

try:
    odds = client.odds.list(sport="basketball_nba")
except RateLimitError:
    # Free tier: 12 req/min. Retry after 1 second.
    import time
    time.sleep(1)
    odds = client.odds.list(sport="basketball_nba")
except AuthenticationError:
    print("Check your SHARPAPI_KEY — get one at sharpapi.io/dashboard/api-keys")

9. Summary — Methods and Plans

TaskMethodPlan
Fetch odds (REST)client.odds.list()Free
Best odds across booksclient.odds.best()Free
Arbitrage detectionclient.opportunities.arbitrage()Hobby
+EV opportunitiesclient.opportunities.ev()Pro
Live SSE streamingclient.stream.odds()Hobby
Historical oddsclient.odds.historical()Pro

Frequently Asked Questions

How do I get sports betting odds in Python?+
Install the SharpAPI Python SDK (pip install sharpapi), set your SHARPAPI_KEY environment variable, and call client.odds.list(sport='basketball_nba'). It returns structured JSON with odds from 32+ sportsbooks. Free tier available with no credit card required.
What Python sports betting API libraries are available?+
SharpAPI offers a first-party sharpapi Python package on PyPI. Other providers like The Odds API require raw requests calls. SharpAPI's SDK includes Pydantic models, type hints, async support, and SSE streaming helpers out of the box.
Is there a free sports betting API for Python?+
Yes. SharpAPI's free tier includes 12 requests/minute (17,280/day) with no credit card required. The Python SDK works on the free tier. Upgrade to Hobby ($79/mo) to unlock SSE streaming and all 32+ sportsbooks.
How do I stream live odds in Python?+
Use SharpAPI's SSE endpoint. The Python SDK includes client.stream.odds() which yields live updates as they arrive. Each update is a delta payload — only changed lines are sent, reducing bandwidth.
Can I get NBA, NFL, and NHL odds in one Python API call?+
Not in a single REST call — each call specifies a sport. But you can fan out calls in parallel using asyncio.gather() or use SSE streaming, which covers all sports in one persistent connection.

Related Resources

Ready to Build?
Start free. Scale when you're ready. No credit card required.

No credit card required