Free bet365 Racing odds API
Horse, harness and greyhound meetings, race cards, runners and results, as JSON over REST. No key, no sign-up, exclusively bet365 odds.
Overview
Racing is a separate product from the match sports. A race is one event with many priced runners, not a head-to-head, so it has its own endpoints and its own shape rather than GET /odds. You get the board of meetings and races, each race card with its runners and Fixed Win price, each-way terms, the full lifecycle status, and finished races with placings and dividends.
Racing is polled over REST, not pushed over the public WebSocket. The /ws feed carries the match sports; for racing, poll /racing. The prices there are last-good and update as bet365 moves them. An empty read is never treated as closed: the last-good runners and prices are kept.
Codes
| Code | Key | Notes |
|---|---|---|
| Horse racing | horse | Thoroughbred and North American thoroughbred. The detailed card adds barrier/draw, weight, jockey, trainer, age, colour/sex, form and career stats, plus the Fixed Place price. |
| Harness | harness | Trots and pacers. The driver is in jockey. The detailed card adds the real race name (full_name) and the start type (start_type: Mobile or Standing). |
| Greyhound | greyhound | Box racing. Runners are keyed by box number; there is no jockey, so jockey is null. |
Endpoints
| Endpoint | Returns |
|---|---|
GET/racing | The board: meetings, races and runners for a code. Params: code=horse|harness|greyhound|all, meeting=<id> (narrows both races and meetings), near=<N> (next N races by jump time). |
GET/racing/race | One race card. Param: id=<race_id>. |
GET/racing/results | Resulted races: placings, starting prices, favourite tag and dividends. Params: code, date=YYYYMMDD (or YYYY-MM-DD). |
Every response carries server_time and each race an updated_at. Invalid parameters return a clear 400 (an unknown code, a non-numeric meeting or race id, a negative near or a date that is not a real calendar date), never a 500. Decimal odds are rounded to two places; the fractional form is exact. A value that is genuinely unknown is null with a stable key, never a sentinel: an unpriced runner has win_odds: null, a greyhound has jockey: null.
Race status
Each race carries a lifecycle status and an in_play flag.
| status | Meaning |
|---|---|
open | Pre-jump, at least one runner priced. |
suspended | Pre-jump, every runner temporarily suspended. |
off | Jumped, the win market closed, no result yet. |
running | Jumped and fixed-odds in-running prices are still moving. |
result_interim | Placings in, dividends not yet declared (correct weight pending). |
result_final | Dividends declared (correct weight / weighed in). |
abandoned | The race was abandoned or postponed. |
in_play is true while a race is off or running (jumped, not yet resulted).
Quickstart
curl "https://moviodds.com/racing?code=harness" curl "https://moviodds.com/racing?code=greyhound&near=5" curl "https://moviodds.com/racing/race?id=202291364" curl "https://moviodds.com/racing/results?code=horse&date=20261006"
import requests
board = requests.get("https://moviodds.com/racing", params={"code": "horse"}, timeout=30).json()
for race in board["races"]:
print(race["course"], race["name"], race["status"])
for r in race["runners"]:
print(" ", r["number"], r["name"], r["win_frac"], r["win_odds"])
Sample response
A trimmed /racing?code=harness race:
{
"server_time": "2026-10-06T02:10:00Z",
"code": "harness",
"meetings": [
{ "meeting_id": "21174179", "code": "harness", "course": "Menangle", "date": "20261006" }
],
"race_count": 1,
"races": [
{
"race_id": "202291364",
"code": "harness",
"number": 1,
"name": "Race 1 Menangle",
"full_name": "Yirribee Pacing Stud Cattlewash Trotters Mobile",
"start_type": "Mobile",
"course": "Menangle",
"jump_utc": "2026-10-06T02:14:00Z",
"going": null,
"distance": "1609m",
"class": null,
"each_way": { "places": 3, "frac_num": 1, "frac_den": 5, "raw": "E/W 1/5 1-2-3" },
"status": "open",
"in_play": false,
"runners": [
{ "sel_id": "140712233", "number": 3, "name": "Island Frankie", "jockey": "Cameron Hart", "win_frac": "2/1", "win_odds": 3.0, "scratched": false, "suspended": false },
{ "sel_id": "140712234", "number": 9, "name": "Casualconnection", "jockey": "Jack Trainor", "win_frac": null, "win_odds": null, "scratched": false, "suspended": true }
],
"updated_at": "2026-10-06T02:09:58Z"
}
]
}
Results
/racing/results returns resulted races. Each placing carries the finishing position, the runner number and name, the starting price (sp_frac exact and sp_odds decimal) and a favourite tag. Exotic dividends such as forecast and tricast carry the winning combination and the declared amount. A race stays result_interim until a dividend amount is declared, then becomes result_final.
FAQ
Is the bet365 racing odds API free?
Yes. GET /racing needs no sign-up and no key. Limits are 300 requests per minute per IP.
Which codes are covered?
Horse racing (thoroughbred and North American thoroughbred), harness (trots and pacers) and greyhound racing.
Is racing pushed over the WebSocket?
No. Racing is polled over REST from /racing. The /ws WebSocket carries the match sports; the racing prices at /racing are last-good and update as bet365 moves them.
Do you have race results and dividends?
Yes. /racing/results returns resulted races with final placings, starting prices, the favourite tag and exotic dividends.