Handball Odds API: Live EHF, Bundesliga & LNH Odds from 70+ Bookmakers (Free Tier)
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 /odds — players["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.