Handball Odds API: Live EHF, Bundesliga & LNH Odds from 70+ Bookmakers (Free Tier)

Handball Odds API - OddsPapi API Blog
How To Guides May 6, 2026

Why Handball Odds Data Is Hard to Find

Handball is the most-watched sport you can’t get API data for. 27 million registered players. Packed arenas across Germany, France, Denmark, Spain, and Poland. Regular €1,000+ per-match handles on the sharp Asian markets for top Bundesliga and LNH Division 1 fixtures.

But try to pull handball odds programmatically and you hit a wall. Goalserve, OddsMatrix, and Sportbex sell handball feeds as enterprise add-ons — annual contracts, minimum commits, no developer tier. The Odds API doesn’t cover handball at all. RapidAPI has a few niche handball endpoints, but none with sharp lines.

OddsPapi covers 293 handball tournaments with up to 78 bookmakers per fixture — including Pinnacle. 1X2, handicaps, totals, halftime markets, all in real-time. The free tier gives you enough calls to build and test a real European handball model.

Handball Odds Coverage: OddsPapi vs The Competition

Feature The Odds API Goalserve / OddsMatrix OddsPapi
Handball coverage None Enterprise only Yes, all tiers
Bookmakers per match ~20 Up to 78
Sharp books (Pinnacle) No Yes
Crypto sportsbooks No Yes (1xBet, Stake, Vave, Blaze, Roobet, Rollbit, Duelbits, BCGame)
US sportsbooks No Yes (DraftKings, BetMGM, BetRivers + 4 more)
Markets per fixture Limited 10+ (1X2, handicaps, totals, halftime)
Tournaments ~30 leagues 293 tournaments
Historical data Paid add-on Free tier
Pricing transparency Sales call required Public
Free tier No 250 req/mo

293 Handball Tournaments: Bundesliga, LNH, Liga Asobal & More

Handball is a European-dominated sport, and OddsPapi’s coverage reflects that. 293 tournaments tracked globally — the deepest public handball feed you’ll find.

Level Examples Bookmakers
International EHF European Championship Qualification, IHF World Championship, Olympics 60-70
European Clubs EHF Champions League, EHF European League, EHF European Cup 60-75
Top Domestic (Men) Bundesliga (Germany), LNH Division 1 (France), Liga Asobal (Spain), Handboldligaen (Denmark) 60-78
Second Divisions 2. HBL (Germany), LNH Proligue (France), Division de Honor Plata (Spain) 20-40
Women’s Leagues Kvindeligaen (Denmark), LFH Division 1 (France), 2. Bundesliga Women (Germany) 20-50
Other Europe HLA Challenge (Austria), Divisao de Honra (Portugal), NB I (Hungary), Premijer Liga (Bosnia) 20-40
Asia-Pacific Japan Handball League, Super Handball League 10-30

That’s real depth. Not just the EHF Champions League top tier — second divisions, women’s leagues, Balkan regional competitions, Japanese domestic. If a bookmaker prices it, we have it.

Handball Markets: 1X2, Handicaps & Totals

Handball matches can go to overtime, which creates two distinct winner markets you need to understand:

Market Market ID Description
1X2 (Full Time Result) 223 Home / Draw / Away at end of regular time. Primary market, offered by 75+ books.
Winner (2-way, including OT) 221 Home / Away including overtime. Pinnacle’s preferred market.
Handicap 22314+ Spread on goal margin (e.g. hc=2.5 means favourite must win by 3+)
Total Goals O/U 22116-22156 Over/Under. Top handball matches total 55-67 goals, so lines sit in that range
First Half Result 10208 1X2 at halftime
First Half Over/Under 10256+ Goals in first half only
Both Teams To Score 104 Trivial in handball (almost always Yes) but priced by some books
Asian Handicap 1024+ Quarter-goal lines (-6, -6.5, -7 etc.) where offered

The handball market catalog has 32,000+ individual market IDs — most are handicap and totals line variants. Don’t hardcode them. Query the catalog and build your own lookup:

r = requests.get(f"{BASE_URL}/markets", params={"apiKey": API_KEY, "sportId": 22})
catalog = r.json()

# Build name lookup for markets and outcomes
market_names = {m["marketId"]: m["marketName"] for m in catalog}
outcome_names = {
    (m["marketId"], o["outcomeId"]): o["outcomeName"]
    for m in catalog for o in m.get("outcomes", [])
}

# All handicap lines available for handball
handicaps = sorted({m["handicap"] for m in catalog if m["marketName"] == "Handicap"})
print(f"Handicap lines: {handicaps}")

Tutorial: Pull Handball Odds with Python

Step-by-step guide to fetching live handball odds from OddsPapi. Every snippet below was tested against the live API.

Step 1: Authentication

OddsPapi uses a query parameter for auth — no headers, no OAuth:

import requests

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.oddspapi.io/v4"

# Test your key
response = requests.get(f"{BASE_URL}/sports", params={"apiKey": API_KEY})
print(response.status_code)  # 200 = you're in

Step 2: Discover Handball Tournaments

Handball is sportId: 22. Pull the full tournament catalog and filter to active leagues:

response = requests.get(
    f"{BASE_URL}/tournaments",
    params={"apiKey": API_KEY, "sportId": 22}
)
tournaments = response.json()
print(f"Total handball tournaments: {len(tournaments)}")

# Filter to tournaments with upcoming fixtures
active = [t for t in tournaments if t.get("futureFixtures", 0) > 0]
active.sort(key=lambda t: -t["futureFixtures"])

for t in active[:10]:
    print(f"  {t['tournamentName']} ({t.get('categoryName', '?')}) - {t['futureFixtures']} fixtures")

Output:

Total handball tournaments: 293
  European Championship Qualification (International) - 64 fixtures
  2. HBL (Germany) - 55 fixtures
  Bundesliga (Germany) - 54 fixtures
  LNH Division 1 (France) - 50 fixtures
  2. Bundesliga, Women (Germany) - 50 fixtures
  HLA Challenge (Austria) - 48 fixtures
  LFH Division 1, Women (France) - 43 fixtures
  Liga Asobal (Spain) - 42 fixtures
  NB I/B (Hungary) - 40 fixtures
  Divisao de Honra (Portugal) - 37 fixtures
  ...

Step 3: Fetch Fixtures

Pull upcoming handball fixtures within a date range (max 10 days per call):

from datetime import datetime, timedelta, timezone
import time

now = datetime.now(timezone.utc)
fr = now.strftime("%Y-%m-%d")
to = (now + timedelta(days=7)).strftime("%Y-%m-%d")

response = requests.get(
    f"{BASE_URL}/fixtures",
    params={"apiKey": API_KEY, "sportId": 22, "from": fr, "to": to}
)
fixtures = response.json()
with_odds = [f for f in fixtures if f["hasOdds"]]

print(f"Fixtures (7 days): {len(fixtures)}")
print(f"With odds: {len(with_odds)}")

# Show top LNH Division 1 fixtures
lnh = [f for f in with_odds if f.get("tournamentName") == "LNH Division 1"]
for f in lnh[:3]:
    print(f"  {f['participant1Name']} vs {f['participant2Name']}")
    print(f"    Kick-off: {f['startTime']}")
    print(f"    Fixture ID: {f['fixtureId']}")

Step 4: Parse Live Odds

Grab odds for a specific fixture. The response is nested — bookmakerOdds → slug → markets → marketId → outcomes → players["0"]:

fixture_id = "id2200015961810510"  # Limoges Handball vs Paris Saint-Germain (LNH Division 1)

response = requests.get(
    f"{BASE_URL}/odds",
    params={"apiKey": API_KEY, "fixtureId": fixture_id}
)
data = response.json()
bookmaker_odds = data["bookmakerOdds"]

print(f"Bookmakers: {len(bookmaker_odds)}")

# Parse 1X2 (market 223) from bwin
bwin = bookmaker_odds["bwin"]["markets"]["223"]["outcomes"]
for outcome_id, outcome in bwin.items():
    price = outcome["players"]["0"]["price"]
    label = {"223": "Home", "224": "Draw", "225": "Away"}[outcome_id]
    print(f"  {label}: {price}")

Output:

Bookmakers: 78
  Home: 5.25
  Draw: 14.0
  Away: 1.24

Step 5: Compare Pinnacle vs Soft Books

Pinnacle prices handball on the 2-way Winner market (221, includes overtime), while soft books use the 3-way 1X2 (223, regular time only). To compare sharp vs soft pricing, convert Pinnacle’s 2-way prices into implied probabilities:

# Pinnacle 2-way (market 221)
pin = bookmaker_odds.get("pinnacle", {}).get("markets", {}).get("221", {}).get("outcomes", {})
pin_home = pin.get("221", {}).get("players", {}).get("0", {}).get("price")
pin_away = pin.get("222", {}).get("players", {}).get("0", {}).get("price")
print(f"Pinnacle (2-way, inc OT)    | Home: {pin_home}   Away: {pin_away}")

# Soft books on 1X2 (market 223)
compare_books = ["bet365", "bwin", "unibet", "draftkings", "betmgm", "stake", "1xbet"]
for slug in compare_books:
    if slug not in bookmaker_odds:
        continue
    m = bookmaker_odds[slug].get("markets", {}).get("223", {}).get("outcomes", {})
    if not m:
        continue
    home = m.get("223", {}).get("players", {}).get("0", {}).get("price")
    draw = m.get("224", {}).get("players", {}).get("0", {}).get("price")
    away = m.get("225", {}).get("players", {}).get("0", {}).get("price")
    print(f"{slug:25s} | Home: {home}   Draw: {draw}   Away: {away}")

Output:

Pinnacle (2-way, inc OT)    | Home: 4.65   Away: 1.17
bwin                      | Home: 5.25   Draw: 14.0   Away: 1.24
unibet                    | Home: 5.2    Draw: 12.5   Away: 1.23
draftkings                | Home: 5.5    Draw: 10.5   Away: 1.21
betmgm                    | Home: 5.25   Draw: 14.0   Away: 1.24
stake                     | Home: 5.2    Draw: 13.0   Away: 1.26
1xbet                     | Home: 4.78   Draw: 10.7   Away: 1.28

The sharp line anchors your expected value. Pinnacle prices Paris Saint-Germain at 1.17 to win including overtime; any 1X2 away price above Pinnacle’s implied probability (roughly 1.19 stripping out draw equity) is positive expected value. 1xBet’s 1.28 away price stands out. This is the logic behind any serious handball arbitrage or value model.

Step 6: Full Script — Handball Best-Odds Scanner

Complete script that scans upcoming handball fixtures and finds the best 1X2 odds across all books — the same logic behind any line-shopping workflow:

import requests, time
from datetime import datetime, timedelta, timezone

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.oddspapi.io/v4"

# Pull upcoming handball fixtures
now = datetime.now(timezone.utc)
fr = now.strftime("%Y-%m-%d")
to = (now + timedelta(days=3)).strftime("%Y-%m-%d")

fixtures_resp = requests.get(
    f"{BASE_URL}/fixtures",
    params={"apiKey": API_KEY, "sportId": 22, "from": fr, "to": to}
)
fixtures = [f for f in fixtures_resp.json() if f["hasOdds"]]

# Focus on top-tier leagues
top_leagues = {"Bundesliga", "LNH Division 1", "Liga Asobal", "Handboldligaen", "EHF Champions League"}
fixtures = [f for f in fixtures if f.get("tournamentName") in top_leagues]

print(f"Scanning {len(fixtures)} top-tier handball fixtures...\n")

for fixture in fixtures[:5]:
    name = f"{fixture['participant1Name']} vs {fixture['participant2Name']}"
    print(f"{name} ({fixture['tournamentName']})")

    odds_resp = requests.get(
        f"{BASE_URL}/odds",
        params={"apiKey": API_KEY, "fixtureId": fixture["fixtureId"]}
    )
    bo = odds_resp.json().get("bookmakerOdds", {})

    # Best 1X2 (market 223) across books
    best = {"223": (0, ""), "224": (0, ""), "225": (0, "")}
    for slug, bdata in bo.items():
        outcomes = bdata.get("markets", {}).get("223", {}).get("outcomes", {})
        for oid, odata in outcomes.items():
            price = odata.get("players", {}).get("0", {}).get("price", 0)
            if price > best[oid][0]:
                best[oid] = (price, slug)

    print(f"  Best Home: {best['223'][0]} ({best['223'][1]})")
    print(f"  Best Draw: {best['224'][0]} ({best['224'][1]})")
    print(f"  Best Away: {best['225'][0]} ({best['225'][1]})")
    print(f"  Books: {len(bo)}\n")

    time.sleep(0.2)  # rate limit safety

78 Bookmakers: Who Covers Handball?

Breakdown of bookmaker types you’ll find on OddsPapi handball fixtures. Verified on a top-tier LNH Division 1 fixture (78 total books):

Category Bookmakers Notes
Sharp Pinnacle 2-way Winner + handicap + totals
US Regulated DraftKings, BetMGM, BetRivers, BetParx, Hard Rock Bet, Borgata, Ballybet 7 US books — unusual for a European sport
Crypto 1xBet, Stake, Vave, Blaze, Roobet, Rollbit, Duelbits, BCGame 8 crypto books with 1X2 + occasional handicap
European Softs Bet365, Unibet, Bwin, Coral, LeoVegas, Winamax, BetWay, 888Sport Full 1X2 coverage, some handicap
Brazilian EstrelaBet, Sportingbet BR, Stake BR, KTO Coverage on EHF and top European leagues
Regional Dafabet, SportyBet, TabTouch, Svenska Spel, Admiral, Quigioco, Goldbet Long tail of regional books

Honest gaps: Singbet, SBOBet, Betfair Exchange, and Polymarket do not currently price handball through our feed. If you need sharp Asian lines, handball isn’t the sport. But if Pinnacle + soft-book line shopping is your edge, OddsPapi gives you 78 books of comparison targets on top European fixtures — far more than any competitor.

Real-Time Handball Odds via WebSocket

REST polling works fine for pre-match handball odds. For in-play, it doesn’t. Handball scoring is fast — 55-67 goals per match, a goal every minute — and lines move every possession. Polling every 30 seconds means you miss every meaningful move.

OddsPapi’s WebSocket feed pushes odds updates the moment bookmakers adjust. When Pinnacle shifts a Liga Asobal totals line from 58.5 to 57.5 after a red card, you see it within milliseconds — across all 78 books simultaneously.

This matters for:

  • Live handicap trading — handball handicaps move sharply on injuries and red cards
  • In-play arb detection — soft books lag Pinnacle by 20-60 seconds on handball, leaving exploitable windows
  • Model validation — compare your live predictions against real-time market prices across dozens of books

Free Historical Handball Data

Most handball data vendors treat historical odds as an enterprise upsell. OddsPapi includes it on the free tier. That means you can:

  • Backtest handball models — did your Bundesliga totals model beat Pinnacle’s closing line over 200 games?
  • Track line movements — how do LNH Division 1 openers move from 48h pre-match to throw-off?
  • Compare bookmaker accuracy — which soft books consistently misprice handball relative to Pinnacle?
  • Build training data — feed historical odds into ML models for match outcome and totals prediction

Pulling the full price history for a finished fixture is one call. Note the endpoint caps at 3 bookmakers per request, and the response shape differs from /oddsplayers["0"] is a list of snapshots, not a single dict:

response = requests.get(
    f"{BASE_URL}/historical-odds",
    params={
        "apiKey": API_KEY,
        "fixtureId": "id2200015961810510",
        "bookmakers": "pinnacle,bet365,bwin",  # max 3
    }
)
history = response.json()

# Iterate snapshot list for 1X2 Home price from bwin
snapshots = history["bookmakers"]["bwin"]["markets"]["223"]["outcomes"]["223"]["players"]["0"]
for snap in snapshots:
    print(f"{snap['createdAt']}  -> {snap['price']}")

Pipe that into your backtesting workflow or export to CSV for model training. For handball specifically, historical data is gold because soft books often misprice lower-tier competitions. The gap is where your edge lives.

FAQ

What sport ID is handball in OddsPapi?

Handball is sportId: 22. Use it on every /fixtures, /tournaments, and /markets call when querying handball data.

Does OddsPapi include Pinnacle handball odds?

Yes. Pinnacle prices handball on 2-way Winner (market 221, includes overtime), handicap, and totals markets. This is the primary differentiator — no other public developer-tier API includes Pinnacle handball lines.

Which handball leagues are covered?

All 293 tournaments where bookmakers price odds, including Bundesliga, LNH Division 1, Liga Asobal, Handboldligaen (Denmark), EHF Champions League, EHF European League, second divisions, women’s leagues, and international qualifiers.

Is there a free handball odds API?

Yes. OddsPapi’s free tier includes 250 requests per month — enough to pull handball fixtures, test the odds endpoint, and build a working model. No credit card required.

What handball markets are available?

1X2 (market 223) is the primary market offered by 75+ books. Pinnacle additionally prices 2-way Winner (221, including OT), Handicap (22314+), and Total Goals (22116-22156). Halftime 1X2 (10208) and halftime totals are also available on many books.

How do I get EHF Champions League odds?

Query /v4/tournaments?sportId=22 and filter on tournamentName == "EHF Champions League" to get the tournament ID. Then pull fixtures with /v4/fixtures?sportId=22&from=...&to=... and filter client-side. Odds come from the /v4/odds endpoint per fixture.

Stop Scraping. Start Building.

Handball has been one of the most underserved sports in the odds API space for years. Goalserve, OddsMatrix, and Sportbex gatekeep it behind enterprise contracts. The Odds API ignores it entirely. OddsPapi covers 293 tournaments with up to 78 bookmakers per fixture — including Pinnacle, eight crypto books, seven US sportsbooks, and the full European soft-book roster.

Get your free API key and start pulling Bundesliga, LNH, Liga Asobal, and EHF Champions League odds in minutes. No credit card. No enterprise sales call. Just data.