Bet365 Live Odds API: Read a Goal Repriced in 4 to 10 Seconds
Bet365 has no public API, and its in-play board is the one people ask for most. The prices sit behind a geo-locked site that reprices every few seconds and suspends every market the moment a ball goes near a goal. OddsPapi carries bet365 as ten slugs, and every one of them keeps pricing after kick-off.
This post is what the bet365 in-play feed did on one Champions League night, measured through the API on 8 September 2026. Real Madrid v Inter, kick-off 19:03 UTC. Three goals, nine suspensions, one final pull three minutes before the whistle, and a full-time result market that moved 133 times on the home leg in-play against 53 times in the entire pre-match window. At each goal bet365 pulled the 1X2, then re-posted a new price 4.0, 8.4 and 10.3 seconds later.
The cadence is the reverse of the pre-match story. Pre-match, bet365 follows a Pinnacle move in a median of 67 minutes. In-play it re-posts a goal inside the time it takes Pinnacle to come back off suspension.
Ten Slugs, and Two Flags That Do Not Describe In-Play
The catalogue held 357 bookmakers on 8 September 2026. Ten of them are bet365.
| Slug | Name | liveOdds | cloneOf |
|---|---|---|---|
bet365 |
bet365 | false | null |
bet365-nj |
bet365 NJ | false | bet365 |
bet365.bet.ar |
bet365 AR | false | null |
bet365.bet.br |
bet365 BR | false | null |
bet365.de |
bet365 DE | false | null |
bet365.es |
bet365 ES | false | null |
bet365.fr |
bet365 FR | false | null |
bet365.gr |
bet365 GR | false | null |
bet365.it |
bet365 IT | false | null |
bet365.nl |
bet365 NL | false | null |
Read that liveOdds column and you would skip bet365 for anything in-play. Then pull a live fixture and the same ten slugs return 277 market IDs with prices that changed twelve seconds before your call. The book-level bookmakerIsActive flag does the same thing: it reads true on bet365 before kick-off, flips to false about half a minute after the first whistle (33 and 35 seconds on the two fixtures we polled through kick-off), and stays false to full time while the prices underneath keep moving. Treat both as pre-match capability flags. The in-play freshness signal is the price-level changedAt, and the in-play availability signals are suspended on the book, marketActive on the market and active on the price.
Old Way vs OddsPapi
| Scraping the bet365 in-play page | OddsPapi | |
|---|---|---|
| Access | Geo-locked site, session tokens, bot detection | ?apiKey= on the query string |
| Live fixture discovery | Parse the in-play lobby | /fixtures with statusName == "Live" |
| Suspensions | Greyed-out DOM, no timestamp | active: false on the price, changedAt on the resume |
| Comparison books | One scraper per book | 287 books on the same live payload, exchanges included |
| In-play history | You record it yourself | /historical-odds keeps every in-play snapshot, free tier |
| Push updates | Poll and hope | WebSocket stream |
Step 1: Find What Is Live Right Now
Authentication is a query parameter. Filter the fixture list on statusName. The trueStartTime field is the real kick-off, which matters later when you cut history into pre-match and in-play.
import datetime as dt
import os
import requests
API_KEY = os.environ["ODDSPAPI_API_KEY"]
BASE = "https://api.oddspapi.io/v4"
now = dt.datetime.now(dt.timezone.utc)
fixtures = requests.get(f"{BASE}/fixtures", params={
"apiKey": API_KEY,
"sportId": 10, # soccer
"from": (now - dt.timedelta(hours=3)).strftime("%Y-%m-%dT%H:%M:%SZ"),
"to": (now + dt.timedelta(hours=1)).strftime("%Y-%m-%dT%H:%M:%SZ"),
}).json()
live = [f for f in fixtures if f["statusName"] == "Live" and f["hasOdds"]]
for f in live[:5]:
print(f["fixtureId"], f["tournamentName"], "|",
f["participant1Name"], "v", f["participant2Name"],
"| kicked off", f["trueStartTime"])
print(len(live), "live fixtures with a board")
id1000033473943718 EFL Trophy | Doncaster Rovers v Huddersfield Town | kicked off 2026-09-08T18:03:23.861Z
id1001441373954156 U20 Copa do Brasil | EC Bahia BA v Alagoinhas AC BA | kicked off 2026-09-08T18:12:49.556Z
id1001441373954656 U20 Copa do Brasil | Gremio FB Porto Alegrense RS v Real SC RS | kicked off 2026-09-08T18:01:43.839Z
id1000001872339814 Championship | Wrexham AFC v Burnley FC | kicked off 2026-09-08T18:46:10.896Z
id1000033172965092 Challenge Cup | Banks O´Dee FC v Forfar Athletic FC | kicked off 2026-09-08T18:48:26.409Z
16 live fixtures with a board
statusId maps 0 to Pre-Game, 1 to Live, 2 to Finished and 3 to Cancelled. A six-hour window around 20:35 UTC on a Tuesday returned 53 live soccer fixtures, from the Champions League down to the Scottish Challenge Cup.
Step 2: Pull bet365 Next to a Sharp and an Exchange
The bookmakers filter takes a comma-separated list. Ask for bet365, Pinnacle and the Betfair exchange on the same fixture and you get three pricing models on one payload: a soft book, a sharp book and a matched-bet ladder.
FIXTURE = "id1000000774165878" # Real Madrid v Inter, UEFA Champions League
BOOKS = "bet365,pinnacle,betfair-ex"
odds = requests.get(f"{BASE}/odds", params={
"apiKey": API_KEY, "fixtureId": FIXTURE, "bookmakers": BOOKS,
}).json()
print("statusId", odds["statusId"], "| kicked off", odds["trueStartTime"])
for slug, book in odds["bookmakerOdds"].items():
markets = book["markets"]
active = [m for m in markets.values()
if any(p["active"] for o in m["outcomes"].values()
for p in o["players"].values())]
print(f"{slug:11} suspended={book['suspended']!s:5} "
f"bookmakerIsActive={book['bookmakerIsActive']!s:5} "
f"markets={len(markets):3} with_active_price={len(active)}")
statusId 1 | kicked off 2026-09-08T19:03:05.910Z
bet365 suspended=False bookmakerIsActive=False markets=278 with_active_price=41
betfair-ex suspended=False bookmakerIsActive=True markets=101 with_active_price=62
pinnacle suspended=False bookmakerIsActive=True markets=189 with_active_price=3
That call landed at 20:50 UTC, six minutes before the final whistle, with Real Madrid 2-1 up. Bet365 still had 41 markets with a live price. Pinnacle had three. The exchange had 62, because a matched market suspends for seconds at a goal and otherwise trades until it runs out of takers.
The 278 market IDs on bet365 are the whole pre-match menu carried into the match, and most of them are dead by then. Across the match, 67 of them took at least one in-play snapshot: the full-time result, double chance, draw no bet, both teams to score, a walking total line, the Asian handicap, second-half result, first and last goal, corner and booking totals, and a player ladder for shots, shots on target and assists. The menu you can trade shrinks with the clock. Across 32 polls in the closing twenty minutes it ran between 15 and 33 markets with an active price.
Step 3: Read a Suspended Price
When bet365 pulls a market, the feed keeps the outcome and sets active: false on it. The price field underneath reads 1.0 while the market is down. Average that into anything and your consensus collapses to evens. The reader below skips the book-level bookmakerIsActive check on purpose, for the reason in the previous section, and refuses a leg the moment its price is inactive.
FULL_TIME_RESULT = "101"
LEGS = {"101": "home", "102": "draw", "103": "away"}
def read_inplay_1x2(book):
if book.get("suspended"):
return None
market = book.get("markets", {}).get(FULL_TIME_RESULT)
if not market or not market.get("marketActive"):
return None
prices = {}
for outcome_id, leg in LEGS.items():
outcome = market["outcomes"].get(outcome_id)
if outcome is None:
return None
price = outcome["players"].get("0")
if price is None or not price["active"]:
return None # suspended leg: bet365 reports 1.0 here
prices[leg] = (price["price"], price["changedAt"])
return prices
for slug, book in odds["bookmakerOdds"].items():
row = read_inplay_1x2(book)
print(slug, "->", row if row else "no active three-way right now")
bet365 -> {'home': (1.071, '2026-09-08T20:50:39.819Z'), 'draw': (9.0, '2026-09-08T20:50:42.982Z'), 'away': (126.0, '2026-09-08T20:50:39.819Z')}
betfair-ex -> {'home': (1.11, '2026-09-08T20:51:01.240Z'), 'draw': (9.8, '2026-09-08T20:51:01.240Z'), 'away': (170.0, '2026-09-08T20:51:01.240Z')}
pinnacle -> no active three-way right now
Every suspension bet365 put on the home leg of that market during the match, reconstructed from /historical-odds. Three of them are goals. The rest are the book pulling the market for a review or a dangerous attack and then re-posting the same or a near-identical number.
| Suspended at (UTC) | Down for | Price before | Price after | What happened |
|---|---|---|---|---|
| 19:14:37 | 37.4 s | 1.667 | 1.667 | Review, same price |
| 19:17:05 | 4.0 s | 1.727 | 1.30 | Real Madrid 1-0 |
| 19:23:19 | 45.3 s | 1.40 | 1.40 | Review, same price |
| 19:26:05 | 8.4 s | 1.40 | 1.125 | Real Madrid 2-0 |
| 20:32:02 | 16.6 s | 1.04 | 1.036 | Review |
| 20:37:10 | 10.3 s, then 4.2 s | 1.03 | 1.25, then 1.222 | Inter 2-1 |
| 20:39:47 | 29.8 s | 1.222 | 1.20 | Review |
| 20:46:52 | 17.5 s | 1.125 | 1.111 | Review |
| 20:53:45 | Closed | 1.012 | none | Pulled for good, three minutes before the whistle |
Each goal cleared in under eleven seconds. Each review took longer, because the book waits for the referee. A downtime under 15 seconds followed by a price that moved is a goal signal you can read off the feed without a scores endpoint.
Step 4: Poll It and Count the Updates
The changedAt timestamp is when OddsPapi last saw that price change. Poll the fixture, remember the last timestamp per leg, and count how many times it advances. One minute of that on the same fixture, eleven polls at a five-second interval:
import time
seen = {} # (slug, market, outcome) -> last changedAt
updates = {}
deadline = time.time() + 60
polls = 0
while time.time() < deadline:
snap = requests.get(f"{BASE}/odds", params={
"apiKey": API_KEY, "fixtureId": FIXTURE, "bookmakers": BOOKS,
}).json()
polls += 1
for slug, book in snap.get("bookmakerOdds", {}).items():
for market_id, market in book["markets"].items():
for outcome_id, outcome in market["outcomes"].items():
price = outcome["players"].get("0")
if not price or not price["active"]:
continue
key = (slug, market_id, outcome_id)
if seen.get(key) != price["changedAt"]:
if key in seen:
updates[slug] = updates.get(slug, 0) + 1
seen[key] = price["changedAt"]
time.sleep(5)
print(f"{polls} polls in 60 seconds")
for slug, n in sorted(updates.items(), key=lambda kv: -kv[1]):
print(f"{slug:11} {n:4} price updates seen")
11 polls in 60 seconds
betfair-ex 857 price updates seen
bet365 65 price updates seen
pinnacle 10 price updates seen
Sixty-five bet365 price updates in one minute of a 2-1 match, five minutes before the whistle. The exchange runs an order of magnitude hotter because every matched bet moves a ladder level. Keep the interval at a second or more between calls to the same endpoint; the feed rate-limits and a 429 body is valid JSON with no bookmakerOdds key, so check status_code before you parse.
Fifteen Minutes From Kick-off
The end of a match is the thin part of the menu. We ran the same loop from kick-off on two CONMEBOL fixtures the same evening, Fluminense v Platense in the Libertadores and Independiente Santa Fe v Vasco da Gama in the Sudamericana, polling each fixture about every twelve seconds for the first fifteen minutes.
| Book | Price updates, all markets | Three-way updates | Polls with a live three-way (of 75) | Median three-way overround |
|---|---|---|---|---|
betfair-ex |
11,688 / 11,430 | 221 / 222 | 70 / 74 | 0.50% / 0.65% |
pinnacle |
5,119 / 4,977 | 108 / 96 | 73 / 64 | 6.58% / 6.65% |
polymarket |
3,918 / 3,396 | 186 / 171 | 75 / 75 | 1.02% / 2.00% |
kalshi |
2,502 / 2,520 | 222 / 222 | 75 / 75 | 1.99% / 1.00% |
draftkings |
1,543 / 1,318 | 15 / 18 | 68 / 62 | 7.06% / 6.93% |
bet365 |
899 / 951 | 17 / 38 | 54 / 65 | 6.53% / 6.51% |
1xbet |
0 / 0 | 0 / 0 | 0 / 0 | suspended from kick-off |
Fluminense v Platense / Santa Fe v Vasco, first fifteen minutes after trueStartTime, 75 polls per fixture about twelve seconds apart, active prices only.
Bet365 switched the three-way to its in-play engine before the whistle. At 21:59:49, forty seconds before kick-off, the four skins we polled snapped from their separate pre-match numbers to one price, 1.60 / 3.40 / 7.00 on Fluminense, and stayed identical on 147 of the 150 in-play polls that followed. bookmakerIsActive flipped to false 33 and 35 seconds after kick-off. 1xBet went the other way: suspended: true two seconds before kick-off on both fixtures, three markets left active, and no price update for the whole window.
The opening menu is the whole pre-match board. Bet365 held 223 to 225 markets with a live price for the first seven minutes on Santa Fe and ten on Fluminense, then cut to between 19 and 46. Pinnacle opened at 82 to 96 and settled at 84 to 88. The three-way itself moved 17 and 38 times on bet365 in those fifteen minutes against 108 and 96 on Pinnacle and 221 and 222 on the exchange. A goalless opening quarter-hour gives a soft book little to reprice, and the margins here run the other way from the Champions League: Pinnacle's in-play three-way sat at 6.58% and 6.65% against bet365's 6.53% and 6.51%, so rank books on the board you are trading rather than on reputation.
What bet365 did reprice, it repriced fast. On Santa Fe v Vasco at 22:08:14 it posted 1.364 on the home leg, the exchange posted 1.63 in the same second, and Pinnacle had suspended five seconds earlier. Bet365 pulled the market seven seconds later and held it for 98 seconds, re-opened at 1.286, then walked it to 2.05 and back to 2.30 inside 25 seconds: a goal, a review, and no goal, as far as the feed can tell. Pinnacle sat the whole episode out for 125 seconds and re-opened at 2.35. The exchange traded through all of it, 1.50 to 1.71 while the review ran.
Step 5: Resolve the Live Total, Do Not Hardcode 1010
Market 1010 is Over/Under 2.5 goals. Pre-match it is the main total on almost every soccer fixture. In-play the main line walks up the ladder with the score, and 2.5 goes dead as soon as the third goal is in. Resolve the live line off the market name and the active flag.
book = odds["bookmakerOdds"]["bet365"]
markets_catalogue = {m["marketId"]: m for m in requests.get(
f"{BASE}/markets", params={"apiKey": API_KEY}).json()}
totals = []
for market_id, market in book["markets"].items():
meta = markets_catalogue.get(int(market_id))
if not meta or meta["marketName"] != "Over Under Full Time":
continue
over = market["outcomes"].get(str(meta["outcomes"][0]["outcomeId"]))
under = market["outcomes"].get(str(meta["outcomes"][1]["outcomeId"]))
if not over or not under:
continue
po, pu = over["players"]["0"], under["players"]["0"]
if po["active"] and pu["active"]:
totals.append((meta["handicap"], po["price"], pu["price"]))
for line, over, under in sorted(totals):
print(f"line {line:4} over {over:6} under {under:6}")
print("hardcoded market 1010 (2.5) active:",
book["markets"].get("1010", {}).get("outcomes", {}).get("1010", {})
.get("players", {}).get("0", {}).get("active"))
line 3.5 over 4.0 under 1.24
hardcoded market 1010 (2.5) active: False
At 2-1, six minutes before the whistle, bet365 had one live total, 3.5, and fifteen total-line IDs in the payload. The 2.5 line took nine in-play snapshots all match before it died. The same resolver works for the Asian handicap: market 1072 is the level line and it took 91 in-play snapshots on bet365 with zero pre-match, because the book opens the in-play handicap fresh at kick-off.
Step 6: Count Repricings From Free History
Historical odds are on the free tier, and the snapshots keep recording through the match. Cut on trueStartTime to separate pre-match from in-play, collapse consecutive identical prices so you count moves and not your own polling, and you have a cadence measure per book.
history = requests.get(f"{BASE}/historical-odds", params={
"apiKey": API_KEY, "fixtureId": FIXTURE,
"bookmakers": "bet365,pinnacle,1xbet", # max 3 per call
}).json()["bookmakers"]
KICK_OFF = odds["trueStartTime"]
def collapse(snapshots):
out = []
for s in snapshots:
if not out or out[-1]["price"] != s["price"]:
out.append(s)
return out
for slug, book in history.items():
snaps = book["markets"][FULL_TIME_RESULT]["outcomes"]["101"]["players"]["0"]
snaps.sort(key=lambda s: s["createdAt"])
pre = [s for s in snaps if s["createdAt"] < KICK_OFF and s["active"]]
live = [s for s in snaps if s["createdAt"] >= KICK_OFF and s["active"]]
print(f"{slug:10} home leg: {len(collapse(pre)) - 1:3} pre-match moves, "
f"{len(collapse(live)) - 1:3} in-play moves "
f"across {len(live)} active snapshots")
bet365 home leg: 53 pre-match moves, 133 in-play moves across 137 active snapshots
pinnacle home leg: 101 pre-match moves, 176 in-play moves across 251 active snapshots
1xbet home leg: 163 pre-match moves, 105 in-play moves across 232 active snapshots
Bet365 moved the home leg 133 times between kick-off and the final whistle, 113 minutes including the break, and 53 times in the days before it. Pinnacle moved 176 times in-play. 1xBet, which reprices an EPL home leg 38 times in the final 24 hours pre-match and answers a Pinnacle move in six minutes, moved 105 times in-play, fewer than either. The median gap between two bet365 moves on that leg was 21.6 seconds. Across every market it traded, bet365 logged 6,812 in-play price changes over 67 markets.
Pull the exchange the same way and you get a clock. betfair-ex needs one bookmaker and one outcomeId per historical call; the home leg alone returned 15,104 in-play snapshots and 378 price changes, a move every seven seconds. Take the moment the exchange price crossed the midpoint of each goal jump and measure who got there when.
| Goal | Exchange home price | bet365 |
draftkings |
1xbet |
pinnacle |
|---|---|---|---|---|---|
| 1-0, 14 min after kick-off | 1.75 to 1.27 | -0.5 s | +157 s | +182 s | +57 s |
| 2-0, 23 min after kick-off | 1.43 to 1.14 | -17 s | -22 s | -10 s | +52 s |
| 2-1, 19 min before the whistle | 1.05 to 1.20 | +8 s | -1 s | +15 s | +30 s |
Negative means the book posted a price past the midpoint before the exchange got there, which happens when the ladder drifts across in stages. Bet365 was within eight seconds of the exchange on all three goals. Pinnacle was last on all three, 30 to 57 seconds behind the exchange. It held its three-way down for 62 seconds after the first goal and 79 after the second, and it had taken the market off altogether at 1.095 from 20:07 until the third goal re-opened it at 1.254. Bet365 kept a price up all the way to 1.012. Different books, different suspension policies, and the flags tell you which one you are looking at.
Ten Slugs, One In-Play Price
Pre-match, the ten bet365 slugs are four price feeds. On Fluminense v Platense an hour before kick-off, seven of them quoted the same three-way and three did not.
| Slug | Pre-match 1X2 | Overround |
|---|---|---|
bet365, bet365-nj, .bet.ar, .bet.br, .es, .gr, .nl |
1.57 / 3.40 / 7.00 | 7.39% |
bet365.de |
1.58 / 3.40 / 7.00 | 6.99% |
bet365.it |
1.615 / 3.40 / 7.00 | 5.62% |
bet365.fr |
1.55 / 3.25 / 6.30 | 11.16% |
pinnacle |
1.653 / 3.45 / 6.73 | 4.34% |
betfair-ex |
1.67 / 3.60 / 7.60 | 0.82% |
In-play that structure collapses on the three-way. Forty seconds before kick-off on both CONMEBOL fixtures the four skins we polled snapped to one full-time result and kept it identical on 147 of 150 in-play polls. On Real Madrid v Inter every active price on the full-time result, the live total, the Asian handicap, both-teams-to-score and draw-no-bet matched across the skins on all 32 polls, changedAt stamps a few milliseconds apart. The German and French skins still ran their own 2.5 total and correct-score ladders into the opening minutes, so dedupe per market rather than per book. On the three-way, the ten slugs are one opinion. Dedupe on the price tuple before you count books: the 287-book payload twenty minutes before the whistle held 118 distinct three-way tuples, and bet365's was shared by eleven slugs, the ten of its own plus 1xBet at that instant. The consensus post covers why that matters for a fair price.
Where bet365 Sits on the In-Play Board
Median three-way overround across 32 polls in the closing twenty minutes of Real Madrid v Inter, 20:37 to 20:45 UTC, complete active three-ways only:
| Book | Polls with a live 1X2 | Median overround | Range |
|---|---|---|---|
betfair-ex |
30 of 32 | 0.54% | 0.02% to 1.94% |
kalshi |
32 of 32 | 1.03% | -0.01% to 3.00% |
polymarket |
32 of 32 | 1.82% | 0.78% to 3.90% |
pinnacle |
22 of 32 | 4.55% | 4.40% to 5.34% |
1xbet |
32 of 32 | 5.77% | 2.98% to 7.18% |
draftkings |
31 of 32 | 5.86% | 5.45% to 6.59% |
bet365 |
30 of 32 | 6.31% | 5.73% to 7.18% |
betmgm |
28 of 32 | 7.18% | 6.49% to 7.83% |
Bet365 charges about 1.8 points more than Pinnacle in-play and about six more than the exchange, and it is up on 30 of 32 polls while Pinnacle is up on 22. That is the trade: the soft book is wider and available; the sharp book is tighter and off for a third of those polls, because Pinnacle takes its three-way down once the favourite goes shorter than about 1.10 and bet365 keeps quoting. A model that needs a live price every poll reads bet365 and the exchange; a model that needs the sharpest price waits for Pinnacle. The live betting API guide covers the polling budget and the WebSocket path for anything faster than a five-second loop.
A Working Checklist
- Find live fixtures with
statusName == "Live"on/fixtures, and cut history ontrueStartTime, neverstartTime. - Ignore
liveOddsandbookmakerIsActivefor bet365 in-play. Readsuspended,marketActiveand the price-levelactive. - A suspended bet365 leg carries
price: 1.0. Filter onactivebefore any arithmetic. - Resolve the live total and handicap off the market name. Market 1010 dies at the third goal.
- Count
changedAtadvances, and collapse identical consecutive prices in history, or you are measuring your own poll rate. - Treat the ten bet365 slugs as one in-play three-way. Dedupe on the tuple, per market.
- Read the exchange next to the soft book. It repriced the home leg every seven seconds all match, so it is your clock.
- Sleep a second between calls to the same endpoint and check
status_codebefore you parse.
FAQ
Does bet365 have a live odds API?
No. Bet365 publishes no developer portal and no in-play endpoint. OddsPapi carries its prices as ten slugs, led by bet365, and the same /odds call that returns the pre-match board keeps returning in-play prices after kick-off, with a changedAt timestamp on every price.
How fast do bet365 live odds update?
On Real Madrid v Inter on 8 September 2026, bet365 moved the home leg of the full-time result 133 times in-play, a median of 21.6 seconds between moves. A one-minute poll at a five-second interval in the closing minutes saw 65 bet365 price updates across its live markets.
What happens to bet365 odds when a goal is scored?
The market suspends. The feed sets active: false on each leg with a placeholder price of 1.0, then re-posts a new price. At the three goals in that match the market was down for 4.0, 8.4 and 10.3 seconds. Reviews and dangerous attacks produced longer suspensions, 17 to 45 seconds, that re-posted the same or a near-identical price.
Are the bet365 regional slugs different prices in-play?
Not on the three-way. Pre-match, bet365.fr, bet365.de and bet365.it quote their own full-time result. Forty seconds before kick-off they snap to one price, and that price stayed identical across the skins on 147 of 150 in-play polls over two fixtures and on all 32 polls of a third. The German and French skins still price the 2.5 total and the correct-score ladder on their own in-play, so dedupe per market.
How does bet365 compare to Pinnacle in-play?
Bet365 ran a median 6.31% three-way overround in the closing twenty minutes of the match against 4.55% for Pinnacle and 0.54% for the Betfair exchange, and it had a live three-way on 30 of 32 polls against Pinnacle's 22. At each goal, bet365 re-posted a price within eight seconds of the exchange, and Pinnacle's first live price landed 30 to 57 seconds after the exchange.
How many in-play markets does bet365 price?
The payload carried 278 bet365 market IDs on the Champions League fixture, and 67 of them took at least one in-play snapshot: the result markets, walking totals, Asian and European handicaps, corners, bookings and a player ladder for shots, shots on target and assists. The count with a live price at any one moment shrinks with the clock: 223 in the opening minutes of Fluminense v Platense, 27 to 40 by the fifteenth minute, and between 15 and 33 in the closing twenty minutes of Real Madrid v Inter.
Can I get bet365 in-play price history?
Yes, on the free tier. /historical-odds keeps every snapshot through the match. Filtered to bet365 alone, the Real Madrid v Inter fixture returned 159,686 snapshots across 278 markets. Cut on trueStartTime to separate the in-play window. The bet365 historical odds guide covers the pre-match side of that archive.
Get the Feed
One key, one endpoint, bet365 in-play next to Pinnacle, three exchanges and 350+ other books on the same fixture. Free historical odds through the match, native market structures for the walking total and the live Asian handicap, and a WebSocket stream when a five-second poll stops being enough.
Get a free key, then read the bet365 access post for the pre-match board and the dynamic odds tutorial for the two timestamps that turn a snapshot into a movement.