Betfair API: Exchange Back, Lay and Depth Prices in Code

James Whitfield
Betfair has an official Exchange API, and it is built for one job: placing bets from a funded Betfair account. A delayed key is free for development. A live key costs a one-off £499, and Betfair states that read-only use of the live key is not permitted.
If you want Betfair prices as data, next to other bookmakers and in one format, 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 Betfair names to request, what the Exchange board contains, how back, lay and depth are returned, and how to pull in-play prices and closing lines. Every number below comes from responses captured on 5 October 2026.
Find the right bookmaker name
Start with /bookmakers. It needs no key and lists every book the API carries. Four of them are Betfair.
curl "https://api.odds-api.io/v3/bookmakers"[
{"name": "Betfair ES", "active": true, "createdAt": "2025-10-14T06:32:00.244395Z"},
{"name": "Betfair Exchange", "active": true, "createdAt": "2025-10-11T11:38:05.549931Z"},
{"name": "Betfair IT", "active": true, "createdAt": "2025-10-14T06:32:00.244395Z"},
{"name": "Betfair Sportsbook", "active": true, "createdAt": "2025-10-11T11:38:05.549931Z"}
]Betfair Exchange is the peer-to-peer market, where customers trade against each other and every outcome has a back price and a lay price. Betfair Sportsbook is the fixed-odds book, where Betfair sets the price. Betfair ES and Betfair IT are the Spanish and Italian sites. Wherever an endpoint takes a bookmaker, pass the name exactly as /bookmakers lists it.
List the matches Betfair prices
/events accepts a bookmaker filter, so the response only holds fixtures that already carry prices from that book.
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=Betfair Exchange"On 5 October this returned 20 Premier League fixtures. 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 the Exchange board contains
Pass an event id and bookmakers=Betfair Exchange to /odds. For Arsenal v Leeds United on 10 October, five days before kickoff, the response carried five Exchange markets: ML, Spread, Totals, Both Teams To Score and Correct Score. Spread ran 20 Asian handicap lines from -4 to +0.75, quarter lines included. Totals carried the 0.5, 1.5 and 2.5 goal lines, and Correct Score listed 16 scorelines.
curl -G "https://api.odds-api.io/v3/odds" \
--data-urlencode "apiKey=YOUR_KEY" \
--data-urlencode "eventId=72221292" \
--data-urlencode "bookmakers=Betfair Exchange" \
--data-urlencode "markets=ML"{
"id": 72221292,
"home": "Arsenal FC",
"away": "Leeds United",
"date": "2026-10-10T11:30:00Z",
"status": "pending",
"urls": {
"Betfair Exchange": "https://www.betfair.com/exchange/plus/en/e/e/e-e-36065339"
},
"bookmakers": {
"Betfair Exchange": [
{
"name": "ML",
"updatedAt": "2026-10-05T10:59:18.058Z",
"odds": [
{
"home": "1.41", "draw": "5.40", "away": "9.20",
"layHome": "1.42", "layDraw": "5.50", "layAway": "9.40",
"depthHome": "40.6", "depthDraw": "16.42", "depthAway": "21",
"depthLayHome": "1128.25", "depthLayDraw": "243.61", "depthLayAway": "37"
}
]
}
]
}
}An Exchange price has three parts. home, draw and away are the best back prices, the odds available to someone backing that outcome. layHome, layDraw and layAway are the best lay prices, the odds available to someone taking the other side. The depth fields give the amount available at each of those prices, so depthLayHome is what was on offer to lay Arsenal at 1.42.
These are top-of-book figures, the best price on each side, not the full ladder. Odds arrive as decimal strings, so parse them before you compare. Each market carries its own updatedAt, and the urls object holds the link to the Betfair market.
Line markets follow the same pattern. Each Spread line has home, away, layHome and layAway with matching depth fields, and each Totals line has over, under, layOver and layUnder.
Exchange and Sportsbook are two different prices
Request both names for the same match and you get two boards. For Arsenal v Leeds, Betfair Sportsbook returned six markets: ML, Draw No Bet, Double Chance, Totals with seven lines from 0.5 to 6.5, Both Teams To Score and Team Total Home. It has no lay side and no depth, because it is a fixed-odds book.
The prices differ too. Sportsbook had the 1X2 at 1.33, 4.75 and 8.5. The Exchange back prices were 1.41, 5.40 and 9.20. Add up the implied probabilities and the Sportsbook line comes to 108.0%, while the Exchange back prices come to 100.3% and the lay prices to 99.2%.
That gap is the bookmaker margin. An exchange has almost none in the price itself, which is why its prices are often used as a reference for the true market. Betfair charges commission on net winnings instead, and the prices in the API do not include it.
A short Python example
This lists the next Premier League fixtures the Exchange prices, then prints the home back and lay price for ten of them, the gap between the two, and the midpoint as a probability. /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"]
BOOK = "Betfair Exchange"
events = requests.get(f"{BASE}/events", params={
"apiKey": KEY,
"sport": "football",
"league": "england-premier-league",
"bookmaker": BOOK,
}).json()
ids = ",".join(str(e["id"]) for e in events[:10])
boards = requests.get(f"{BASE}/odds/multi", params={
"apiKey": KEY,
"eventIds": ids,
"bookmakers": BOOK,
"markets": "ML",
}).json()
for board in boards:
markets = {m["name"]: m["odds"] for m in board["bookmakers"].get(BOOK, [])}
ml = markets.get("ML", [{}])[0]
if "layHome" not in ml:
continue
back, lay = float(ml["home"]), float(ml["layHome"])
mid = 1 / ((1 / back + 1 / lay) / 2)
print(f'{board["home"]} v {board["away"]}: '
f'back {back:.2f} lay {lay:.2f} '
f'gap {(lay / back - 1) * 100:.1f}% '
f'mid {mid:.2f} ({100 / mid:.1f}%)')Run against the live API on 5 October, the first lines of output were:
Arsenal FC v Leeds United: back 1.41 lay 1.42 gap 0.7% mid 1.41 (70.7%)
Aston Villa v Brentford FC: back 2.76 lay 2.78 gap 0.7% mid 2.77 (36.1%)
Chelsea FC v AFC Bournemouth: back 1.75 lay 1.76 gap 0.6% mid 1.75 (57.0%)
Ipswich Town v Fulham FC: back 2.82 lay 2.84 gap 0.7% mid 2.83 (35.3%)
Hull City v Everton FC: back 3.85 lay 3.95 gap 2.6% mid 3.90 (25.6%)
Liverpool FC v Manchester City: back 2.68 lay 2.70 gap 0.7% mid 2.69 (37.2%)The gap is a quick liquidity check. On the busiest fixtures the back and lay prices sat one tick apart, a gap of about 0.7%. On Hull City v Everton it was 2.6%, so the midpoint there is a rougher estimate.
In-play prices
The Exchange stays open after kickoff. At 11:05 UTC on a Monday, it was pricing 4 of the 5 live football matches, 9 of the first 10 live tennis matches and 2 of the 3 live baseball games. The live basketball, ice hockey and cricket matches at that moment had no Exchange prices.
The board changes shape in play. Japan v New Zealand carried ML, Draw No Bet, Double Chance, Spread, Totals and Both Teams To Score. A live tennis match carried ML and ML 2nd Set. 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.
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 Betfair Exchange to your selection before you connect. The live odds guide on this blog covers the stream, reconnects and replay in detail.
Closing lines, with back and lay
Closing odds are the usual benchmark for testing a pricing model. /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" \
--data-urlencode "bookmakers=Betfair Exchange,Betfair Sportsbook"Each event comes back with its final score and the closing board. For the Exchange that includes the lay prices and depth at the close. The home prices for the Premier League weekend of 12 to 14 September:
Match Score Exchange home back / lay Sportsbook home
Aston Villa v Nottingham Forest 1-2 2.36 / 2.38 2.25
AFC Bournemouth v Brentford FC 2-2 2.38 / 2.40 2.38
Chelsea FC v Hull City 2-2 1.24 / 1.25 1.20
Crystal Palace v Ipswich Town 2-3 2.22 / 2.24 2.10
Liverpool FC v Fulham FC 0-0 1.56 / 1.57 1.50
Tottenham Hotspur v Everton FC 0-0 2.08 / 2.10 2.00
Sunderland AFC v Arsenal FC 0-2 6.60 / 6.80 6.50
Coventry City v Brighton & Hove Albion 0-5 4.10 / 4.20 3.90
Manchester United v Manchester City 0-1 3.20 / 3.25 3.10
Leeds United v Newcastle United 4-1 2.44 / 2.46 2.30The Sportsbook closed below the Exchange back price in nine of the ten matches and level in one, which is the margin again, this time measured at the close.
Getting started
Create a key at odds-api.io, add Betfair Exchange and Betfair Sportsbook to your selected bookmakers, and run the Python example above. The Betfair pages in the sportsbooks section list the sports we cover for each, and the API docs describe every endpoint used here.
