Tutorials

How to Get Bet365 Odds via API in Python (2026 Guide)

How to Get Bet365 Odds via API in Python (2026 Guide)

Bet365 is the world's largest online sportsbook — but they don't offer a public API. No developer portal, no documentation, no OAuth flow. If you want Bet365 football odds programmatically, your options have traditionally been scraping (fragile, against terms of service, constant breakage) or paying $100-150+ per month for a single-bookmaker data feed.

UKOddsApi solves this. It provides Bet365 odds alongside 24 other UK bookmakers and exchanges — all through a single REST API. In this tutorial, you'll pull live Bet365 Premier League odds in under 5 minutes with Python.

What you'll build

By the end of this tutorial, you'll have a Python script that:

  • Connects to the UKOddsApi and authenticates with your API key
  • Fetches today's Premier League fixtures
  • Pulls Bet365 odds for every match across multiple markets
  • Compares Bet365 prices against other UK bookmakers to find the best odds
  • Outputs a clean table showing where Bet365 is offering the best (or worst) value

Prerequisites

Step 1: Verify your API key

Every request to UKOddsApi uses the X-Api-Key header. Let's confirm your key works:

import requests

API_KEY = "your_api_key_here"
BASE_URL = "https://api.ukoddsapi.com"

headers = {"X-Api-Key": API_KEY}

# Verify the key is valid
response = requests.get(f"{BASE_URL}/v1/auth/verify", headers=headers)
data = response.json()

if data.get("ok"):
    print("✅ API key is valid")
else:
    print("❌ Invalid API key — check your dashboard at ukoddsapi.com")

Step 2: See which bookmakers are available

Before pulling odds, let's see the full list of UK bookmakers available through the API:

response = requests.get(f"{BASE_URL}/v1/bookmakers", headers=headers)
bookmakers = response.json()["bookmakers"]

print(f"📚 {len(bookmakers)} bookmakers available:\n")

for bm in bookmakers:
    bm_type = "🔄 Exchange" if bm["type"] == "exchange" else "📗 Sportsbook"
    print(f"  {bm_type}  {bm['name']} ({bm['bookmaker_code']})")

Output:

📚 26 bookmakers available:

  📗 Sportsbook  10Bet (UO001)
  📗 Sportsbook  888sport (UO002)
  📗 Sportsbook  Bet365 (UO004)
  📗 Sportsbook  BetVictor (UO005)
  🔄 Exchange     Betfair (UO006)
  📗 Sportsbook  Betfred (UO007)
  📗 Sportsbook  Betway (UO008)
  📗 Sportsbook  BoyleSports (UO012)
  📗 Sportsbook  Coral (UO013)
  📗 Sportsbook  Ladbrokes (UO015)
  🔄 Exchange     Matchbook (UO017)
  📗 Sportsbook  Paddy Power (UO018)
  📗 Sportsbook  Sky Bet (UO020)
  📗 Sportsbook  Spreadex (UO022)
  📗 Sportsbook  Unibet (UO024)
  📗 Sportsbook  William Hill (UO027)
  ... and more

Notice that — unlike other odds APIs — UKOddsApi includes every major UK high street bookmaker: Bet365, Sky Bet, Paddy Power, William Hill, Ladbrokes, Coral, Betfred, BetVictor, and more. Plus exchanges like Betfair and Matchbook.

Step 3: Get today's Premier League fixtures

from datetime import date

today = date.today().isoformat()

response = requests.get(
    f"{BASE_URL}/v1/football/events",
    headers=headers,
    params={
        "schedule_date": today,
        "league": "premier-league",
    }
)

events = response.json()["events"]
print(f"⚽ {len(events)} Premier League matches today:\n")

for event in events:
    print(f"  {event['event_title']}")
    print(f"    Kick-off: {event['kickoff_utc']}")
    print(f"    Event ID: {event['event_id']}")
    print()

Output:

⚽ 3 Premier League matches today:

  Arsenal vs Chelsea
    Kick-off: 2026-04-25T15:00:00Z
    Event ID: evt_arsenal_chelsea_2026_04_25

  Liverpool vs Manchester United
    Kick-off: 2026-04-25T17:30:00Z
    Event ID: evt_liverpool_manutd_2026_04_25

  Brighton vs Tottenham
    Kick-off: 2026-04-25T20:00:00Z
    Event ID: evt_brighton_spurs_2026_04_25

Step 4: Pull Bet365 odds for a match

Now let's get Bet365 odds for a specific fixture. We'll filter by bookmaker code UO004 (Bet365):

event_id = events[0]["event_id"]  # First match

response = requests.get(
    f"{BASE_URL}/v1/football/events/{event_id}/odds",
    headers=headers,
    params={
        "package": "core",
        "bookmaker_codes": "UO004",  # Bet365 only
        "odds_format": "decimal",
    }
)

odds_data = response.json()
print(f"📊 Bet365 odds for {odds_data['event_title']}")
print(f"   Captured at: {odds_data['captured_at']}\n")

for market in odds_data["markets"]:
    print(f"  📈 {market['market_name']} ({market['market_group']})")
    for sel in market["selections"]:
        print(f"     {sel['selection_name']}: {sel['odds']}")
    print()

Output:

📊 Bet365 odds for Arsenal vs Chelsea
   Captured at: 2026-04-25T14:32:10.459641Z

  📈 Win Market (main)
     Arsenal: 1.85
     Draw: 3.60
     Chelsea: 4.20

  📈 Both Teams to Score (main)
     Yes: 1.72
     No: 2.00

  📈 Over/Under 2.5 Goals (main)
     Over 2.5: 1.66
     Under 2.5: 2.20

  📈 Total Corners Over/Under (corners)
     Over 9.5: 1.90
     Under 9.5: 1.90

Step 5: Compare Bet365 against all UK bookmakers

This is where it gets powerful. Let's pull odds from ALL bookmakers and find where Bet365 offers the best price — and where other bookmakers beat them:

# Get odds from ALL bookmakers
response = requests.get(
    f"{BASE_URL}/v1/football/events/{event_id}/odds/best",
    headers=headers,
    params={
        "package": "core",
        "odds_format": "decimal",
    }
)

best_odds = response.json()

print(f"🏆 Best odds comparison for {best_odds['event_title']}\n")

for market in best_odds["markets"]:
    print(f"  📈 {market['market_name']}")
    for sel in market["selections"]:
        best_bookie = sel["bookmaker_name"]
        best_price = sel["odds"]
        print(f"     {sel['selection_name']}: {best_price} @ {best_bookie}")
    print()

Output:

🏆 Best odds comparison for Arsenal vs Chelsea

  📈 Win Market
     Arsenal: 1.91 @ Paddy Power
     Draw: 3.70 @ BoyleSports
     Chelsea: 4.33 @ William Hill

  📈 Both Teams to Score
     Yes: 1.80 @ Sky Bet
     No: 2.10 @ Coral

  📈 Over/Under 2.5 Goals
     Over 2.5: 1.72 @ Betfred
     Under 2.5: 2.30 @ BetVictor

Step 6: Build a Bet365 value checker

Now let's combine everything into a practical tool. This script compares Bet365's prices against the best available odds across all UK bookmakers and tells you where Bet365 is offering poor value:

import requests
from datetime import date

API_KEY = "your_api_key_here"
BASE_URL = "https://api.ukoddsapi.com"
headers = {"X-Api-Key": API_KEY}

BET365_CODE = "UO004"

def get_todays_matches(league="premier-league"):
    """Fetch today's fixtures for a league."""
    response = requests.get(
        f"{BASE_URL}/v1/football/events",
        headers=headers,
        params={
            "schedule_date": date.today().isoformat(),
            "league": league,
        }
    )
    return response.json().get("events", [])

def compare_bet365_odds(event_id):
    """Compare Bet365 odds against the best available price."""

    # Get ALL bookmaker odds
    response = requests.get(
        f"{BASE_URL}/v1/football/events/{event_id}/odds",
        headers=headers,
        params={"package": "core", "odds_format": "decimal"}
    )
    all_odds = response.json()

    # Get best odds
    response = requests.get(
        f"{BASE_URL}/v1/football/events/{event_id}/odds/best",
        headers=headers,
        params={"package": "core", "odds_format": "decimal"}
    )
    best_odds = response.json()

    print(f"\n{'='*60}")
    print(f"⚽ {all_odds['event_title']}")
    print(f"{'='*60}")

    # Build lookup: market_name -> selection_name -> {bet365_odds, best_odds, best_bookie}
    # First, extract Bet365 odds from the full response
    bet365_prices = {}
    for market in all_odds["markets"]:
        mname = market["market_name"]
        bet365_prices[mname] = {}
        for sel in market["selections"]:
            if sel["bookmaker_code"] == BET365_CODE:
                bet365_prices[mname][sel["selection_name"]] = sel["odds"]

    # Then compare against best odds
    for market in best_odds["markets"]:
        mname = market["market_name"]
        print(f"\n  📈 {mname}")
        print(f"  {'Selection':<20} {'Bet365':>8} {'Best':>8} {'Best Bookie':<16} {'Edge':>8}")
        print(f"  {'-'*62}")

        for sel in market["selections"]:
            sname = sel["selection_name"]
            best_price = sel["odds"]
            best_bookie = sel["bookmaker_name"]
            b365_price = bet365_prices.get(mname, {}).get(sname)

            if b365_price:
                edge = ((best_price / b365_price) - 1) * 100
                flag = "✅" if best_bookie == "Bet365" else "⚠️"
                print(f"  {flag} {sname:<18} {b365_price:>8.2f} {best_price:>8.2f} {best_bookie:<16} {edge:>+7.1f}%")
            else:
                print(f"  ❓ {sname:<18} {'N/A':>8} {best_price:>8.2f} {best_bookie:<16}")

# Run it
matches = get_todays_matches()
if not matches:
    print("No Premier League matches today. Try another league:")
    matches = get_todays_matches(league="championship")

for match in matches[:3]:  # First 3 matches
    compare_bet365_odds(match["event_id"])

Output:

============================================================
⚽ Arsenal vs Chelsea
============================================================

  📈 Win Market
  Selection            Bet365     Best Best Bookie         Edge
  --------------------------------------------------------------
  ✅ Arsenal              1.85     1.85 Bet365              +0.0%
  ⚠️ Draw                 3.60     3.70 BoyleSports         +2.8%
  ⚠️ Chelsea              4.20     4.33 William Hill        +3.1%

  📈 Both Teams to Score
  Selection            Bet365     Best Best Bookie         Edge
  --------------------------------------------------------------
  ⚠️ Yes                  1.72     1.80 Sky Bet             +4.7%
  ⚠️ No                   2.00     2.10 Coral               +5.0%

  📈 Over/Under 2.5 Goals
  Selection            Bet365     Best Best Bookie         Edge
  --------------------------------------------------------------
  ⚠️ Over 2.5             1.66     1.72 Betfred             +3.6%
  ⚠️ Under 2.5            2.20     2.30 BetVictor           +4.5%

This instantly shows where Bet365 is competitive and where you're leaving value on the table by not checking other UK bookmakers.

Step 7: Get Bet365 player props (Pro plan)

If you're on the Pro plan, you can access player props — goalscorer odds, shots, cards, and more — from Bet365 and every other UK bookmaker:

# Use package=full to include player props and team props
response = requests.get(
    f"{BASE_URL}/v1/football/events/{event_id}/odds",
    headers=headers,
    params={
        "package": "full",
        "bookmaker_codes": "UO004",  # Bet365
        "market": "goalscorer",      # Filter to goalscorer markets
        "odds_format": "decimal",
    }
)

props = response.json()
print(f"🎯 Bet365 Player Props — {props['event_title']}\n")

for market in props["markets"]:
    print(f"  📈 {market['market_name']}")
    # Show top 5 selections by odds (shortest price = most likely)
    sorted_sels = sorted(market["selections"], key=lambda x: x["odds"])
    for sel in sorted_sels[:5]:
        print(f"     {sel['selection_name']}: {sel['odds']}")
    print()

Output:

🎯 Bet365 Player Props — Arsenal vs Chelsea

  📈 Anytime Goalscorer
     Kai Havertz: 2.50
     Bukayo Saka: 3.00
     Nicolas Jackson: 3.20
     Gabriel Jesus: 3.50
     Cole Palmer: 3.75

  📈 Player Shots Over/Under
     Bukayo Saka Over 1.5 Shots: 1.44
     Cole Palmer Over 1.5 Shots: 1.57
     Kai Havertz Over 1.5 Shots: 1.65

Compare Bet365's goalscorer odds against all 25+ UK bookmakers to find the best price for every player — something no other odds API can do.

What to build next

Now you have Bet365 odds flowing through a clean API, here are some ideas:

  • Odds comparison website — show the best odds across all UK bookmakers for every Premier League match
  • Telegram alert bot — get notified when Bet365 drops below a certain price on a market you're watching
  • Value bet finder — compare Bet365 retail odds against Betfair Exchange to identify +EV opportunities
  • Arbitrage scanner — use the built-in /v1/football/arbitrage endpoint to find guaranteed-profit opportunities across UK bookmakers (Scale plan)

Full working script

Here's everything combined into a single file you can save and run:

"""
bet365_odds_checker.py

Compare Bet365 football odds against all UK bookmakers.
Uses UKOddsApi — sign up free at https://ukoddsapi.com

Usage:
    pip install requests
    python bet365_odds_checker.py
"""

import requests
from datetime import date

# ─── Configuration ───────────────────────────────────────
API_KEY = "your_api_key_here"  # Get yours at ukoddsapi.com
BASE_URL = "https://api.ukoddsapi.com"
BET365_CODE = "UO004"
LEAGUE = "premier-league"  # Try: championship, league-one, champions-league
# ─────────────────────────────────────────────────────────

headers = {"X-Api-Key": API_KEY}


def verify_key():
    r = requests.get(f"{BASE_URL}/v1/auth/verify", headers=headers)
    if not r.json().get("ok"):
        raise SystemExit("❌ Invalid API key. Get one at ukoddsapi.com")
    print("✅ API key verified\n")


def get_events(league, schedule_date=None):
    params = {"league": league}
    if schedule_date:
        params["schedule_date"] = schedule_date
    r = requests.get(f"{BASE_URL}/v1/football/events", headers=headers, params=params)
    return r.json().get("events", [])


def check_bet365_value(event_id):
    # Full odds from all bookmakers
    r_all = requests.get(
        f"{BASE_URL}/v1/football/events/{event_id}/odds",
        headers=headers,
        params={"package": "core", "odds_format": "decimal"}
    )
    all_data = r_all.json()

    # Best odds per selection
    r_best = requests.get(
        f"{BASE_URL}/v1/football/events/{event_id}/odds/best",
        headers=headers,
        params={"package": "core", "odds_format": "decimal"}
    )
    best_data = r_best.json()

    print(f"\n{'='*65}")
    print(f"⚽  {all_data['event_title']}")
    print(f"    Kick-off: {all_data['kickoff_utc']}")
    print(f"{'='*65}")

    # Extract Bet365 prices
    b365 = {}
    for mkt in all_data["markets"]:
        b365[mkt["market_name"]] = {
            sel["selection_name"]: sel["odds"]
            for sel in mkt["selections"]
            if sel["bookmaker_code"] == BET365_CODE
        }

    # Compare
    for mkt in best_data["markets"]:
        mn = mkt["market_name"]
        print(f"\n  {mn}")
        print(f"  {'Selection':<22}{'Bet365':>8}{'Best':>8}  {'Bookie':<16}{'Edge':>7}")
        print(f"  {'-'*63}")
        for sel in mkt["selections"]:
            sn = sel["selection_name"]
            bp = sel["odds"]
            bb = sel["bookmaker_name"]
            b3 = b365.get(mn, {}).get(sn)
            if b3:
                edge = ((bp / b3) - 1) * 100
                flag = "✅" if bb == "Bet365" else "⚠️"
                print(f"  {flag} {sn:<20}{b3:>8.2f}{bp:>8.2f}  {bb:<16}{edge:>+6.1f}%")


def main():
    verify_key()

    today = date.today().isoformat()
    events = get_events(LEAGUE, schedule_date=today)

    if not events:
        print(f"No {LEAGUE} matches today. Showing upcoming fixtures...\n")
        events = get_events(LEAGUE)

    print(f"Found {len(events)} fixtures\n")

    for event in events[:5]:
        check_bet365_value(event["event_id"])


if __name__ == "__main__":
    main()

API reference

Endpoint Description
GET /v1/bookmakers List all 25+ UK bookmakers with codes
GET /v1/football/events Get fixtures by date, league, or status
GET /v1/football/events/{id}/odds Full odds from all bookmakers
GET /v1/football/events/{id}/odds/best Best price per selection
GET /v1/football/markets Browse all available market types
POST /v1/football/odds/batch Odds for up to 50 events in one call
GET /v1/football/arbitrage Find arbitrage opportunities by date

All endpoints use the X-Api-Key header for authentication. Odds are returned in decimal format by default — pass odds_format=fractional or odds_format=american to change.


UKOddsApi provides odds from 25+ UK bookmakers including Bet365, Sky Bet, Paddy Power, William Hill, Ladbrokes, Coral, Betfred, BetVictor, 888sport, and more. Sign up free and start building.