How do I turn three-way soccer odds into probabilities in Python?
A club's season of matches with every sportsbook's home, draw and away closing price. This removes the margin to get probabilities and scores them against the results.
Code verified October 12, 2026. One call to get_odds, 5 credits.
The call
season is the year it starts, so 2025 is 2025-26. A season of one club's matches costs 2 credits per match returned. Pass date or game_id for fewer, and league for another competition.
import requests
import pandas as pd
API_KEY = "YOUR_API_KEY"
resp = requests.post(
"https://mcp.strikerapi.com/v1/get_odds",
headers={"x-api-key": API_KEY},
json={
"season": 2025,
"team": "ARS",
"limit": 40,
},
timeout=60,
)
resp.raise_for_status()
data = resp.json()["data"]
import math
def implied(odds):
return 100 / (odds + 100) if odds > 0 else -odds / (-odds + 100)
rows = []
for g in data["games"]:
for b in g["books"]:
prices = [b["home_ml_close"], b["draw_ml_close"], b["away_ml_close"]]
if None in prices:
continue
raw = [implied(p) for p in prices]
fair = [p / sum(raw) for p in raw]
rows.append({
"match": g["home"]["abbrev"] + " v " + g["away"]["abbrev"],
"book": b["provider"],
"overround": sum(raw) - 1,
"p_home": fair[0], "p_draw": fair[1], "p_away": fair[2],
"p_result": fair["HDA".index(g["result"])],
"gap_vs_api": abs(fair[0] - b["close_prob"]["home"]),
})
df = pd.DataFrame(rows)
print(df.head(6).round(3).to_string(index=False))
print(df.groupby("book").agg(matches=("match", "count"), overround=("overround", "mean"), p_result=("p_result", "mean")).round(3))
print("log loss:", round(-df["p_result"].map(math.log).mean(), 3))
print("largest gap to the no-margin probability in the response:", round(df["gap_vs_api"].max(), 3))
Replace YOUR_API_KEY with a key from your dashboard. Python needs requests and pandas (pip install requests pandas). JavaScript runs on Node 18 or newer, or in the browser.
What comes back
The data object of the response, trimmed to the first rows. Every field is real output from the run above.
{
"games": [
{
"game_id": "740604",
"season": 2025,
"stage": "Regular Season",
"date": "2025-08-17",
"starts_at": "2025-08-17T15:30:00.000Z",
"status": "final",
"status_detail": "FT",
"home": {
"team_id": "360",
"abbrev": "MAN",
"name": "Manchester United",
"score": 0
},
"away": {
"team_id": "359",
"abbrev": "ARS",
"name": "Arsenal",
"score": 1
},
"result": "A",
"neutral_site": null,
"venue": "Old Trafford",
"city": "Manchester",
"attendance": 73475,
"books": [
{
"provider": "888sport",
"source": "the_odds_api",
"home_ml_open": 250,
"home_ml_close": 280,
"draw_ml_open": 240,
"draw_ml_close": 250,
"away_ml_open": 100,
"away_ml_close": -105,
"close_prob": {
"home": 0.248,
"draw": 0.269,
"away": 0.483,
"overround": 0.061
},
"home_handicap_open": null,
"home_handicap_close": null,
"handicap_home_odds": null,
"handicap_away_odds": null,
"total_open": null,
"total_close": null,
"over_odds": null,
"under_odds": null,
"captured_at": "2025-08-17T15:20:38.000Z"
},
{
"provider": "Bet 365",
"source": "espn",
"home_ml_open": null,
"home_ml_close": 280,
"draw_ml_open": null,
"draw_ml_close": 270,
"away_ml_open": null,
"away_ml_close": -110,
"close_prob": {
"home": 0.249,
"draw": 0.256,
"away": 0.495,
"overround": 0.057
},
"home_handicap_open": null,
"home_handicap_close": null,
"handicap_home_odds": null,
"handicap_away_odds": null,
"total_open": null,
"total_close": 2.75,
"over_odds": -111,
"under_odds": -105,
"captured_at": "2026-10-08T03:00:31.942Z"
},
"...7 more"
],
"outcome": {
"result": "A",
"median_total": 2.5,
"median_home_handicap": 0.5,
"over": false,
"home_covered": false
}
},
"...37 more"
],
"count": 319,
"next_offset": null
}What to do next
- get_line_movement (10 credits). Snapshots of a match's three-way line before kick-off.
- get_ratings (2 credits). Our Elo ratings, to set a rating gap beside the market's probability.
More guides
Start with 500 free credits every month
No card. REST or MCP.