Bet365 API: Pre-Match, Live and Historical Odds in Code

James Whitfield
Bet365 does not offer a public API. There is no developer portal, no API key to apply for and no price list for odds access. To use Bet365 prices in your own code, you read them from an odds API that carries the book.
This guide shows how that works on the Odds-API.io v3 API: which bookmaker name to request, what a Bet365 board contains, how quickly in-play prices arrive, and how to pull price history and closing lines. Every number below comes from responses captured on 21 September 2026.
Find the right bookmaker name
Start with /bookmakers. It needs no key and lists every book the API carries. Two of them are Bet365.
curl "https://api.odds-api.io/v3/bookmakers"[
{"name": "Bet365", "active": true, "createdAt": "2025-10-11T11:38:05.549931Z"},
{"name": "bet365 NJ", "active": true, "createdAt": "2025-10-14T06:32:00.244395Z"}
]Bet365 is the main international site. bet365 NJ is the New Jersey sportsbook. Wherever an endpoint takes a bookmaker, pass the name exactly as /bookmakers lists it.
List the matches Bet365 prices
/events accepts a bookmaker filter, so the response only holds fixtures that already carry Bet365 odds.
curl -G "https://api.odds-api.io/v3/events" \
--data-urlencode "apiKey=YOUR_KEY" \
--data-urlencode "sport=football" \
--data-urlencode "league=england-premier-league" \
--data-urlencode "bookmaker=Bet365"With no to parameter, the window is the next 14 days. Each event comes back with its id, teams, kickoff, sport and league, and the id is what every odds endpoint asks for.
What a Bet365 board contains
Pass an event id and bookmakers=Bet365 to /odds. For Arsenal v Leeds United on 10 October, nearly three weeks before kickoff, the response carried 49 Bet365 markets.
The core markets use the API's standard names: ML for the 1X2, Spread for the Asian handicap ladder and Totals for goal lines. The ladders are deep. Spread ran 17 lines from -3.5 to +0.5, quarter lines included, and Totals ran 19 lines from 0.5 to 7.5. Around them sit the markets people know from the Bet365 app: Correct Score with 37 outcomes, Anytime Goalscorer with 38 players, Player To Score or Assist with 114 selections, Half Time / Full Time, Winning Margin, Both Teams To Score and more.
Most applications need a handful of those. The markets parameter takes up to 20 names, is case-insensitive, and trims the response to what you ask for.
curl -G "https://api.odds-api.io/v3/odds" \
--data-urlencode "apiKey=YOUR_KEY" \
--data-urlencode "eventId=72221292" \
--data-urlencode "bookmakers=Bet365" \
--data-urlencode "markets=ML,Totals"{
"id": 72221292,
"home": "Arsenal FC",
"away": "Leeds United",
"date": "2026-10-10T11:30:00Z",
"status": "pending",
"urls": {
"Bet365": "https://www.bet365.com/#/AC/B1/C1/D8/E200549688/F3/"
},
"bookmakers": {
"Bet365": [
{
"name": "ML",
"updatedAt": "2026-09-21T10:22:55.348Z",
"odds": [{ "home": "1.333", "draw": "5.000", "away": "8.000" }]
},
{
"name": "Totals",
"updatedAt": "2026-09-21T01:04:14.776Z",
"odds": [
{ "hdp": 2.25, "over": "1.525", "under": "2.425" },
{ "hdp": 2.5, "over": "1.725", "under": "2.075" },
{ "hdp": 2.75, "over": "1.950", "under": "1.900" }
]
}
]
}
}The Totals ladder is shortened here to the three lines around 2.5. Odds arrive as decimal strings, so parse them before you compare. Each market carries its own updatedAt, which tells you how fresh that price is. The urls object holds the Bet365 event link, which is what sits behind a bet button in a comparison product.
If none of the names you pass match, the event comes back with an empty bookmakers object. That usually means a typo in a market name. Names such as Match Winner or Over/Under do not exist in the API; use ML and Totals.
A short Python example
This lists the next Premier League fixtures Bet365 prices, then pulls the 1X2 and the 2.5 goal line for ten of them. /odds/multi takes up to ten event ids and counts as a single request against your hourly limit.
import os
import requests
BASE = "https://api.odds-api.io/v3"
KEY = os.environ["ODDS_API_KEY"]
events = requests.get(f"{BASE}/events", params={
"apiKey": KEY,
"sport": "football",
"league": "england-premier-league",
"bookmaker": "Bet365",
}).json()
ids = ",".join(str(e["id"]) for e in events[:10])
boards = requests.get(f"{BASE}/odds/multi", params={
"apiKey": KEY,
"eventIds": ids,
"bookmakers": "Bet365",
"markets": "ML,Totals",
}).json()
for board in boards:
markets = {m["name"]: m["odds"] for m in board["bookmakers"].get("Bet365", [])}
ml = markets.get("ML", [{}])[0]
main = next((o for o in markets.get("Totals", []) if o["hdp"] == 2.5), {})
print(f'{board["home"]} v {board["away"]}: '
f'{ml.get("home")} / {ml.get("draw")} / {ml.get("away")} '
f'O2.5 {main.get("over")} U2.5 {main.get("under")}')Run against the live API on 21 September, the first lines of output were:
Chelsea FC v AFC Bournemouth: 1.700 / 4.000 / 4.200 O2.5 1.425 U2.5 2.750
Ipswich Town v Fulham FC: 2.750 / 3.400 / 2.450 O2.5 1.775 U2.5 2.025
Sunderland AFC v Brighton & Hove Albion: 2.750 / 3.300 / 2.500 O2.5 1.925 U2.5 1.925
Manchester United v Tottenham Hotspur: 1.666 / 3.900 / 4.500 O2.5 1.525 U2.5 2.425
Liverpool FC v Manchester City: 2.900 / 3.600 / 2.200 O2.5 1.575 U2.5 2.350In-play prices
Bet365 prices a large share of live matches across football, tennis, basketball and table tennis. At 10:20 UTC on a Monday morning, with little football on, Bet365 was pricing 2 of the 4 live football matches, 5 of the first 10 live tennis matches, 6 of the first 10 live table tennis matches and an Australian NBL game in the second quarter.
The board changes shape once a match starts. The live tennis match carried set and game markets such as Totals 3rd Set, Correct Score 3rd Set and ML Set 3 Game 10. The in-play updatedAt stamps were within a few seconds of the request time.
To poll, list what is in play with /events/live and fetch prices with /odds/multi. Live events also carry a clock object with the minute, the period and whether the clock is running, so you can show the match state next to the price.
Polling suits a handful of matches. For more, the WebSocket stream pushes each change as it happens. It sends updates for the bookmakers selected on your account, so add Bet365 to your selection before you connect. The live odds guide on this blog covers the stream, reconnects and replay in detail.
Price history for a Bet365 market
Bet365 is one of the books the API records movement history for. /odds/movements returns the opening price and each recorded change for one market on one event.
curl -G "https://api.odds-api.io/v3/odds/movements" \
--data-urlencode "apiKey=YOUR_KEY" \
--data-urlencode "eventId=72221292" \
--data-urlencode "bookmaker=Bet365" \
--data-urlencode "market=ML"{
"eventid": "72221292",
"bookmaker": "Bet365",
"opening": {"timestamp": 1789233735178, "home": 1.25, "draw": 5.5, "away": 12},
"movements": [
{"timestamp": 1789233735178, "home": 1.25, "draw": 5.5, "away": 12},
{"timestamp": 1789380461479, "home": 1.25, "draw": 5.5, "away": 11},
{"timestamp": 1789767943716, "home": 1.285, "draw": 5.25, "away": 9.5},
{"timestamp": 1789835085097, "home": 1.3, "draw": 5, "away": 9},
{"timestamp": 1789942724412, "home": 1.333, "draw": 5, "away": 8}
]
}Between 12 and 20 September, Bet365 moved Arsenal out from 1.25 to 1.333 and brought Leeds in from 12.0 to 8.0. Timestamps in this response are Unix milliseconds.
For a market with a line, add marketLine, for example market=Totals&marketLine=2.5. In the Totals history the over price is reported as home and the under price as away. For Arsenal v Leeds, the 2.5 over moved from 1.65 to 1.725 over the same period.
Closing lines for backtesting
Closing odds are the usual benchmark for grading a model or a betting record. /historical/closing-lines returns them for every settled event across up to ten leagues in one request, for up to 30 bookmakers and a date range of up to 366 days. It is available on paid plans.
curl -G "https://api.odds-api.io/v3/historical/closing-lines" \
--data-urlencode "apiKey=YOUR_KEY" \
--data-urlencode "sport=football" \
--data-urlencode "leagues=england-premier-league" \
--data-urlencode "from=2026-09-12T00:00:00Z" \
--data-urlencode "to=2026-09-15T00:00:00Z" \
--data-urlencode "markets=ML,Totals" \
--data-urlencode "bookmakers=Bet365"Each event comes back with its final score and the closing board. Bet365's closing prices for the Premier League weekend of 12 to 14 September:
Match Result Bet365 close 1 / X / 2 Over / Under 2.5
Aston Villa v Nottingham Forest 1-2 2.20 / 3.40 / 3.25 1.875 / 1.975
AFC Bournemouth v Brentford FC 2-2 2.25 / 3.60 / 3.10 1.65 / 2.20
Chelsea FC v Hull City 2-2 1.222 / 6.50 / 12.00 1.40 / 2.85
Crystal Palace v Ipswich Town 2-3 2.15 / 3.75 / 3.10 1.70 / 2.10
Liverpool FC v Fulham FC 0-0 1.50 / 4.50 / 5.25 1.425 / 2.75
Tottenham Hotspur v Everton FC 0-0 2.00 / 3.60 / 3.50 1.70 / 2.10
Sunderland AFC v Arsenal FC 0-2 6.00 / 3.60 / 1.60 2.10 / 1.70
Coventry City v Brighton & Hove Albion 0-5 3.70 / 3.80 / 1.909 1.675 / 2.15
Manchester United v Manchester City 0-1 3.00 / 3.75 / 2.20 1.525 / 2.425
Leeds United v Newcastle United 4-1 2.30 / 3.50 / 3.00 1.70 / 2.10To go deeper on one match, find past fixtures with /historical/events and fetch a settled event's full board with /historical/odds.
Getting started
Create a key at odds-api.io, add Bet365 to your selected bookmakers, and run the Python example above. The Bet365 page in the sportsbooks section lists the sports we cover for it, and the API docs describe every endpoint used here.
