MoviOdds Docs
API docs Sports Bet Builder Python moviodds.com

bet365 historical odds API

Every bet365 price change we have recorded, pre-match and in-play, as a timeline per selection. Free, no key.

What you get

GET /history?fi=<match> returns the recorded price points for a match, oldest first. Each point has the time, the selection and its price, and whether it was suspended.

Pair it with closing lines for the last price before kickoff and /results for the final score.

Request

curl "https://moviodds.com/history?fi=201714836&sel=59223458"
ParameterUse
fiMatch id (required). Pre-match and live ids both work and are merged.
groupOnly one market group, e.g. 40 for soccer Full Time Result.
selOnly one selection.
from, toTime window, RFC 3339 (2026-10-04T12:00:00Z) or Unix seconds.
limitMax rows, default 5000, up to 50000. truncated is true when you hit it.

Sample response

A real timeline: the underdog's money line in LV Raiders v KC Chiefs (NFL, 4 October 2026), trimmed to its first and last points. It drifted from 2.80 to 2.90 before kickoff.

{
  "fixture_id": "201714836",
  "fixture_ids": ["201714836", "202267109"],
  "count": 25,
  "truncated": false,
  "limit": 5000,
  "points": [
    {"ts": "2026-10-02T17:56:23Z", "fixture_id": "201714836", "group_id": "1441", "group_name": "Money Line", "sel_id": "59223458", "label": "KC Chiefs", "odds_dec": 2.8, "odds_frac": "9/5", "suspended": false},
    …
    {"ts": "2026-10-04T20:01:03Z", "fixture_id": "201714836", "group_id": "1441", "group_name": "Money Line", "sel_id": "59223458", "label": "KC Chiefs", "odds_dec": 2.9, "odds_frac": "19/10", "suspended": false},
    {"ts": "2026-10-04T20:21:01Z", "fixture_id": "201714836", "group_id": "1441", "group_name": "Money Line", "sel_id": "59223458", "label": "KC Chiefs", "odds_dec": 2.9, "odds_frac": "19/10", "suspended": false}
  ]
}

Each point carries the same identity fields as /odds: group_name and label, plus side, line, handicap and n2 on the markets that use them (a totals leg, for example, carries "side": "O", "line": "2.5"). Fields are present only when they have a value.

Export to CSV

import csv, requests

h = requests.get("https://moviodds.com/history",
                 params={"fi": "201714836", "group": "1441"}, timeout=60).json()
with open("history.csv", "w", newline="") as f:
    w = csv.writer(f)
    w.writerow(["ts", "sel_id", "label", "odds_dec", "suspended"])
    for p in h["points"]:
        w.writerow([p["ts"], p["sel_id"], p.get("label", ""), p["odds_dec"], p["suspended"]])
print(h["count"], "rows")

Each point already names its market and selection (group_name, label, side, line), so you usually do not need a second call. If you want the full market list for a match, read its quotes from /odds: each quote has the same sel_id.

FAQ

Is the bet365 historical odds API free?

Yes. No sign-up and no key. /history allows 120 requests per minute per IP.

How far back does the history go?

To September 2026, when we started recording. Every price change since then is kept.

Does it include in-play odds?

Yes. Pre-match and in-play prices are in the same timeline, and points carry suspended when the market was closed.

Which sports and markets?

All 24 sports we cover and every market bet365 prices, from match winners to player props.

Are these really bet365 odds?

Yes, only bet365's own prices. MoviOdds is an independent project and is not affiliated with bet365.

More: closing lines · live WebSocket · all 24 sports · Python client · API docs