Football Odds API: Real-Time Soccer Data

Football Odds API - OddsPapi API Blog
How To Guides March 18, 2026

Why You Need a Football Odds API

Football is the world’s most-bet sport. If you’re building anything with betting data — a model, a scanner, a dashboard — you need odds from more than 20 bookmakers. You need the sharps. You need Asian Handicaps. And you need it in JSON, not scraped HTML.

Most APIs cover 40 soft bookmakers and call it a day. OddsPapi covers 140+ bookmakers per match, including Pinnacle, Singbet, and Betfair Exchange — the books that actually set the market. That’s 1X2, Asian Handicaps (every line), Both Teams To Score, Over/Under, and 460+ markets total. All on a free tier.

Football Odds Coverage: OddsPapi vs The Competition

Feature The Odds API SportsGameOdds OddsPapi
Bookmakers per match ~15-20 ~30 140+
Sharp books (Pinnacle, Singbet) No No Yes
Asian Handicap markets Limited Limited Full (every line)
Over/Under lines 2.5 only Some 1.5, 2.5, 3.5+
BTTS market Yes Yes Yes (109+ books)
Tournaments ~30 leagues ~50 leagues 1,372 tournaments
Betfair Exchange No No Yes
Free tier 500 req/mo Limited 250 req/mo

1,372 Tournaments, Every League That Matters

OddsPapi covers 1,372 football tournaments — from the Premier League, La Liga, Bundesliga, Serie A, and Ligue 1 down to lower divisions, youth leagues, and women’s football. Champions League, Europa League, MLS, Brasileiro Serie A, Eredivisie, Primeira Liga, Scottish Premiership, Turkish Super Lig, and hundreds more.

Coverage extends to every competition that bookmakers price. If a bookmaker prices it, we have it.

Football Markets: From 1X2 to Asian Handicaps

Each football fixture on OddsPapi can have 464+ unique markets. Here are the key ones with their market IDs — you’ll need these for API calls:

Market Market ID Outcomes Books
Full Time Result (1X2) 101 Home (101), Draw (102), Away (103) 125+
Both Teams To Score 104 Yes (104), No (105) 109+
Over/Under 2.5 Goals 1010 Over (1010), Under (1011) 119+
Over/Under 1.5 Goals 1012 Over (1012), Under (1013) 101+
Over/Under 3.5 Goals 1014 Over (1014), Under (1015) 98+
Asian Handicap -0.5 1068 Home (1068), Away (1069) 53
Asian Handicap 0 1072 Home (1072), Away (1073) 22
Asian Handicap -1 1064 Home (1064), Away (1065) 24
Asian Handicap +0.5 1076 Home (1076), Away (1077) 30

Why Asian Handicaps Matter

Asian Handicaps are how sharps bet football. Each line has its own market ID — not one generic “Asian Handicap” market. This means you can compare Pinnacle’s -0.5 line directly against Bet365’s -0.5 line, or track how the -1.0 line moves across 24 bookmakers independently.

Other APIs collapse these into a single market or don’t cover them at all. OddsPapi gives you every line (from +0.5 through -1.5 and beyond) as a distinct, queryable market.

Python Tutorial: Football Odds in 5 Steps

Step 1: Setup

import requests
from datetime import datetime, timedelta

API_KEY = "YOUR_API_KEY"  # Free at oddspapi.io
BASE_URL = "https://api.oddspapi.io/v4"
SPORT_ID = 10  # Soccer/Football

Step 2: Browse Tournaments

def get_tournaments():
    """Get all football tournaments."""
    response = requests.get(f"{BASE_URL}/tournaments", params={
        "apiKey": API_KEY,
        "sportId": SPORT_ID
    })
    tournaments = response.json()
    print(f"{len(tournaments)} tournaments available")
    return tournaments

tournaments = get_tournaments()

# Filter to top leagues
for t in tournaments:
    if any(name in t.get("tournamentName", "") for name in ["Premier League", "La Liga", "Bundesliga", "Serie A", "Champions"]):
        print(f"  {t['tournamentName']} (ID: {t['tournamentId']})")

Step 3: Get Today’s Fixtures

def get_fixtures(sport_id=SPORT_ID):
    """Get today's football fixtures with odds."""
    today = datetime.now().strftime("%Y-%m-%d")
    tomorrow = (datetime.now() + timedelta(days=1)).strftime("%Y-%m-%d")

    response = requests.get(f"{BASE_URL}/fixtures", params={
        "apiKey": API_KEY,
        "sportId": sport_id,
        "from": today,
        "to": tomorrow
    })

    fixtures = response.json()
    with_odds = [f for f in fixtures if f.get("hasOdds")]
    print(f"{len(with_odds)} fixtures with odds today")
    return with_odds

fixtures = get_fixtures()
for f in fixtures[:10]:
    print(f"  {f['participant1Name']} vs {f['participant2Name']} ({f['tournamentName']})")

Step 4: Fetch Odds from 140+ Bookmakers

def get_odds(fixture_id):
    """Get odds from all bookmakers for a fixture."""
    response = requests.get(f"{BASE_URL}/odds", params={
        "apiKey": API_KEY,
        "fixtureId": fixture_id
    })
    return response.json()

# Pick a fixture and get odds
fixture = fixtures[0]
odds = get_odds(fixture["fixtureId"])
bookmakers = list(odds.get("bookmakerOdds", {}).keys())
print(f"{len(bookmakers)} bookmakers pricing {fixture['participant1Name']} vs {fixture['participant2Name']}")

Step 5: Compare Odds Across Bookmakers

def compare_odds(odds_data, market_id="101"):
    """Compare odds across all bookmakers for a market.

    Market 101 = Full Time Result (1X2)
    Outcomes: 101=Home, 102=Draw, 103=Away
    """
    results = []

    for slug, bookie in odds_data.get("bookmakerOdds", {}).items():
        market = bookie.get("markets", {}).get(market_id)
        if not market:
            continue

        row = {"bookmaker": slug}
        for outcome_id, outcome in market.get("outcomes", {}).items():
            for player_id, player in outcome.get("players", {}).items():
                price = player.get("price")
                if outcome_id == "101":
                    row["home"] = price
                elif outcome_id == "102":
                    row["draw"] = price
                elif outcome_id == "103":
                    row["away"] = price

        if "home" in row:
            results.append(row)

    # Sort by best home odds
    results.sort(key=lambda x: x.get("home", 0), reverse=True)

    print(f"\n1X2 Odds from {len(results)} bookmakers:")
    print(f"{'Bookmaker':<20} {'Home':>8} {'Draw':>8} {'Away':>8}")
    print("-" * 46)
    for r in results[:10]:
        print(f"{r['bookmaker']:<20} {r.get('home', 'N/A'):>8} {r.get('draw', 'N/A'):>8} {r.get('away', 'N/A'):>8}")

    # Find best prices
    best_home = max(results, key=lambda x: x.get("home", 0))
    best_draw = max(results, key=lambda x: x.get("draw", 0))
    best_away = max(results, key=lambda x: x.get("away", 0))

    print(f"\nBest Home: {best_home['home']} @ {best_home['bookmaker']}")
    print(f"Best Draw: {best_draw['draw']} @ {best_draw['bookmaker']}")
    print(f"Best Away: {best_away['away']} @ {best_away['bookmaker']}")

compare_odds(odds)

Advanced: Compare Asian Handicap Lines

This is where it gets interesting for sharps. Pull Asian Handicap -0.5 odds from every bookmaker and compare:

def compare_asian_handicap(odds_data, market_id="1068"):
    """Compare Asian Handicap -0.5 across bookmakers.

    Market 1068 = Asian Handicap -0.5
    Outcomes: 1068=Home -0.5, 1069=Away +0.5
    """
    results = []

    for slug, bookie in odds_data.get("bookmakerOdds", {}).items():
        market = bookie.get("markets", {}).get(market_id)
        if not market:
            continue

        row = {"bookmaker": slug}
        for outcome_id, outcome in market.get("outcomes", {}).items():
            for player_id, player in outcome.get("players", {}).items():
                price = player.get("price")
                if outcome_id == "1068":
                    row["home_minus"] = price
                elif outcome_id == "1069":
                    row["away_plus"] = price

        if "home_minus" in row:
            results.append(row)

    results.sort(key=lambda x: x.get("home_minus", 0), reverse=True)

    print(f"\nAsian Handicap -0.5 from {len(results)} bookmakers:")
    print(f"{'Bookmaker':<20} {'Home -0.5':>10} {'Away +0.5':>10}")
    print("-" * 42)
    for r in results[:10]:
        print(f"{r['bookmaker']:<20} {r.get('home_minus', 'N/A'):>10} {r.get('away_plus', 'N/A'):>10}")

compare_asian_handicap(odds)

This is where the edge lives. Soft bookmakers are slow to adjust Asian Handicap lines. Pinnacle moves first. If you can spot when Bet365’s -0.5 is still 1.95 but Pinnacle has already moved to 1.85, you’ve found value.

Free Historical Football Odds

Need to backtest your football model? Check Closing Line Value? Analyze how Asian Handicap lines moved before kickoff?

OddsPapi includes historical odds on the free tier. Pull past odds for any fixture, any bookmaker, any market. Most APIs charge extra for historical data — or lock it behind enterprise plans. We include it free because backtesting is how you build models that actually work.

Already using historical data? Check out our Bet365 Historical Odds Guide for a deep dive on strategy.

FAQ: Football Odds API

What sport ID is football/soccer?

Sport ID 10. Use sportId=10 in all requests. This covers all football/soccer tournaments worldwide — Premier League through to lower divisions.

How many bookmakers cover football?

Up to 140+ bookmakers per match for top leagues (Premier League, Bundesliga, Champions League). Lower leagues may have 30-50 bookmakers depending on the competition.

Do you cover Asian Handicaps?

Yes. Every line has its own market ID — from Asian Handicap +0.5 (market 1076) through -1.5 (market 1060) and beyond. Unlike other APIs, we don’t collapse them into one generic market. You get each line separately so you can compare the same handicap across bookmakers.

Is the API free?

The free tier gives you 250 requests per month. That’s enough to scan fixtures, pull odds, and compare prices across bookmakers. No credit card required.

Do you have Pinnacle football odds?

Yes. Pinnacle, Singbet, SBOBet, and other sharp bookmakers are included alongside 130+ soft books. You get the sharp prices that actually set the market.

What about live/in-play football odds?

Yes. Filter fixtures by status to find live matches. For real-time updates without polling, the Pro tier includes WebSocket streaming — odds pushed to your client the instant they change.

Start Building with Football Odds Data

Whether you’re building a model, scanning for value, or comparing lines across 140 bookmakers — start with 250 free API requests. No credit card, no enterprise sales call.

Get Your Free API Key at OddsPapi.io

Stop scraping. Stop paying for data that only covers soft books. Get the sharps, the Asian Handicaps, and the historical data — all in one API.