tutorial

How to Map Bookmaker Brand Names to Stable Codes

When building an application that consumes pre-match football odds, one of the first headaches you hit is bookmaker naming. "Bet365" might be "bet365.com" somewhere else, or "William Hill" could be "WH". These inconsistencies break your code. Learning how to map bookmaker brand names to stable codes is critical for any robust odds integration.

This guide will walk you through the process of creating a reliable mapping. We'll use the UK Odds API, which provides stable, unique identifiers for each bookmaker. This approach ensures your application remains consistent, even if a bookmaker rebrands or changes how they present their name. You get clean, pre-match football odds JSON without the constant maintenance burden of scraping.

abstract data flow, mapping bookmaker logos to generic codes, clean interface

Prerequisites for Bookmaker Mapping

Before you dive into the code, ensure you have a few things set up. These steps are standard for any API integration. Having them ready will make the process smoother.

Here's what you'll need:

  • An API Key for UK Odds API: You can sign up for a free tier to get started. This key authenticates your requests.
  • Python 3.x: Our code examples will use Python, a common language for data processing and API interaction.
  • requests library: Install it using pip install requests. This library simplifies HTTP requests in Python.
  • Basic understanding of JSON: The API responses are in JSON format.

This tutorial focuses on a practical, code-driven approach. We'll show you exactly how to fetch the necessary data and build your mapping.

Step 1: Fetching the Bookmaker Catalog

The first step in learning how to map bookmaker brand names to stable codes is to retrieve the official list of bookmakers and their assigned stable codes from the API. The UK Odds API provides a dedicated endpoint for this: /v1/bookmakers. This endpoint returns a JSON array of all supported bookmakers, each with a unique bookmaker_code (e.g., UO001) and its human-readable name.

Here's how you can make this request using Python:

import os
import requests

# Load your API key from environment variables for security
API_KEY = os.environ.get("UKODDSAPI_KEY", "YOUR_API_KEY")
BASE_URL = "https://api.ukoddsapi.com"
HEADERS = {"X-Api-Key": API_KEY}

def get_bookmakers():
    """Fetches the list of supported bookmakers from the API."""
    try:
        response = requests.get(f"{BASE_URL}/v1/bookmakers", headers=HEADERS, timeout=10)
        response.raise_for_status()  # Raise an exception for HTTP errors
        return response.json()
    except requests.exceptions.RequestException as e:
        print(f"Error fetching bookmakers: {e}")
        return None

bookmaker_data = get_bookmakers()

if bookmaker_data:
    print("Fetched bookmaker data successfully:")
    for bm in bookmaker_data.get("bookmakers", [])[:3]: # Print first 3 for brevity
        print(f"  Code: {bm['bookmaker_code']}, Name: {bm['name']}")
else:
    print("Failed to fetch bookmaker data.")

This Python script defines a function get_bookmakers that sends a GET request to the /v1/bookmakers endpoint. It includes your API key in the X-Api-Key header, which is required for authentication. Always load your API key from environment variables or a secure configuration system, not hardcode it directly in your script. The try-except block handles potential network or API errors gracefully.

The response from this endpoint will look something like this:

{
  "schema_version": "1.0",
  "count": 27,
  "bookmakers": [
    { "bookmaker_code": "UO001", "name": "10Bet", "type": "sportsbook", "region": "uk" },
    { "bookmaker_code": "UO002", "name": "888sport", "type": "sportsbook", "region": "uk" },
    { "bookmaker_code": "UO003", "name": "Bet365", "type": "sportsbook", "region": "uk" },
    { "bookmaker_code": "UO004", "name": "Betfair (Sportsbook)", "type": "sportsbook", "region": "uk" },
    { "bookmaker_code": "UO005", "name": "Betfair (Exchange)", "type": "exchange", "region": "uk" },
    { "bookmaker_code": "UO027", "name": "William Hill", "type": "sportsbook", "region": "uk" }
  ],
  "note": "Example only — response is truncated."
}

Each object in the bookmakers array contains a bookmaker_code and a name. The bookmaker_code is the stable, unique identifier you'll use in your application. The name is the common brand name. This mapping is your foundation for consistent data handling.

Step 2: Storing and Mapping the Codes

Once you have the bookmaker catalog, the next logical step in how to map bookmaker brand names to stable codes explained is to store this information in a way that's easily accessible within your application. A dictionary (or hash map in other languages) is ideal for this. You can create two mappings: one from bookmaker_code to name and another from name to bookmaker_code. This allows for flexible lookups depending on your needs.

Here's how you can build these mappings in Python:

# Assuming bookmaker_data was successfully fetched from Step 1

bookmaker_code_to_name = {}
bookmaker_name_to_code = {}

if bookmaker_data and bookmaker_data.get("bookmakers"):
    for bm in bookmaker_data["bookmakers"]:
        code = bm["bookmaker_code"]
        name = bm["name"]
        bookmaker_code_to_name[code] = name
        bookmaker_name_to_code[name.lower()] = code # Store names in lowercase for easier lookup

    print("\nBuilt mappings:")
    print(f"Code to Name (sample): {list(bookmaker_code_to_name.items())[:3]}")
    print(f"Name to Code (sample): {list(bookmaker_name_to_code.items())[:3]}")

    # Example lookup
    print(f"\nLookup 'UO003': {bookmaker_code_to_name.get('UO003', 'Not Found')}")
    print(f"Lookup 'bet365': {bookmaker_name_to_code.get('bet365', 'Not Found')}")
else:
    print("No bookmaker data available to build mappings.")

In this snippet, we iterate through the bookmakers array from the API response. For bookmaker_name_to_code, we store the bookmaker name in lowercase. This makes lookups more robust, as user input or external data might vary in casing (e.g., "bet365", "Bet365", "BET365"). You can extend this by handling common aliases if needed, though the API's provided names are generally consistent.

These dictionaries now serve as your internal reference. When you receive odds data, you'll get bookmaker_code values. You can then use bookmaker_code_to_name to display the human-readable names to your users. Conversely, if you need to filter by a bookmaker name, you can use bookmaker_name_to_code to get the correct stable code for your API requests. This is a crucial part of a robust how to map bookmaker brand names to stable codes integration.

database table with two columns, one for stable codes and one for bookmaker names, connected to a Python script

Step 3: Using Stable Codes in Odds Requests

With your bookmaker mappings in place, you can now confidently fetch pre-match football odds and correctly associate them with their respective bookmakers. The UK Odds API returns odds data with these stable bookmaker_code values, ensuring consistency across all responses.

Let's see how to fetch odds for a specific event and then use our mapping to display the bookmaker names:

# Assuming bookmaker_code_to_name mapping is already built from Step 2

def get_football_events(date_str):
    """Fetches football events for a given date."""
    try:
        response = requests.get(
            f"{BASE_URL}/v1/football/events",
            headers=HEADERS,
            params={"schedule_date": date_str, "has_odds": "true", "per_page": "1"},
            timeout=30,
        )
        response.raise_for_status()
        return response.json()
    except requests.exceptions.RequestException as e:
        print(f"Error fetching events: {e}")
        return None

def get_event_odds(event_id):
    """Fetches odds for a specific event."""
    try:
        response = requests.get(
            f"{BASE_URL}/v1/football/events/{event_id}/odds",
            headers=HEADERS,
            params={"package": "core", "odds_format": "decimal"},
            timeout=60,
        )
        response.raise_for_status()
        return response.json()
    except requests.exceptions.RequestException as e:
        print(f"Error fetching odds for event {event_id}: {e}")
        return None

# --- Main execution ---
if bookmaker_code_to_name:
    # 1. Fetch an event
    today_events = get_football_events("2026-04-25") # Example date
    if not today_events or not today_events.get("events"):
        print("No events found for today with odds.")
    else:
        first_event = today_events["events"][0]
        event_id = first_event["event_id"]
        event_title = f"{first_event['home_team']} vs {first_event['away_team']}"
        print(f"\nFetching odds for event: {event_title} (ID: {event_id})")

        # 2. Fetch odds for that event
        event_odds = get_event_odds(event_id)
        if event_odds and event_odds.get("markets"):
            print(f"Odds for {event_odds['event_title']}:")
            # Iterate through markets and selections to display odds with bookmaker names
            for market in event_odds["markets"][:1]: # Just first market for example
                print(f"\n  Market: {market['market_name']}")
                for selection in market["selections"][:3]: # Just first 3 selections
                    bookmaker_code = selection["bookmaker_code"]
                    bookmaker_name = bookmaker_code_to_name.get(bookmaker_code, f"Unknown ({bookmaker_code})")
                    print(f"    Selection: {selection['selection_name']}, Odds: {selection['odds']}, Bookmaker: {bookmaker_name}")
        else:
            print("No odds found for this event.")
else:
    print("Bookmaker mappings not available. Cannot fetch and display odds.")

This script first fetches a list of football events for a specific date using /v1/football/events. It then picks the first event and retrieves its detailed pre-match odds using /v1/football/events/{event_id}/odds. When iterating through the odds, it uses the bookmaker_code from each selection and our bookmaker_code_to_name dictionary to print the human-readable bookmaker name alongside the odds.

A typical odds response for a single event will contain a markets array, and each market will have selections. Within each selection, you'll find the bookmaker_code that links back to your mapping:

{
  "event_id": "EV0000000000001",
  "event_title": "Manchester United vs Arsenal",
  "kickoff_utc": "2026-04-25T15:00:00Z",
  "markets": [
    {
      "market_id": "MA001",
      "market_name": "Match Winner",
      "market_group": "main",
      "selections": [
        {
          "selection_name": "Manchester United",
          "odds": 2.50,
          "bookmaker_code": "UO003",
          "status": "active"
        },
        {
          "selection_name": "Draw",
          "odds": 3.40,
          "bookmaker_code": "UO003",
          "status": "active"
        },
        {
          "selection_name": "Arsenal",
          "odds": 2.80,
          "bookmaker_code": "UO003",
          "status": "active"
        },
        {
          "selection_name": "Manchester United",
          "odds": 2.45,
          "bookmaker_code": "UO027",
          "status": "active"
        },
        {
          "selection_name": "Draw",
          "odds": 3.35,
          "bookmaker_code": "UO027",
          "status": "active"
        }
      ]
    }
  ],
  "note": "Example only — response is truncated."
}

By consistently using these stable bookmaker_code values and your local mapping, you ensure that your application always displays the correct bookmaker names, regardless of any external changes. This is the core benefit of using a structured UK bookmaker odds API like ukoddsapi.com.

Common Mistakes When Mapping Bookmaker Data

Even with a clear process for how to map bookmaker brand names to stable codes, developers can encounter pitfalls. Avoiding these common mistakes will save you debugging time and ensure your data remains accurate.

  • Hardcoding bookmaker names or IDs: Never embed specific bookmaker names or their scraped IDs directly into your application logic. If a bookmaker rebrands or changes their internal ID, your code will break. Always rely on the API's stable codes.
  • Not refreshing the bookmaker catalog: Bookmakers can be added or removed from the API's coverage. Fetch the /v1/bookmakers endpoint periodically (e.g., daily or weekly) to keep your local mapping up-to-date.
  • Case sensitivity issues: When mapping name to bookmaker_code, always convert the incoming name to a consistent case (e.g., lowercase) before lookup. This prevents "Bet365" and "bet365" from being treated as different entities.
  • Ignoring unknown bookmaker codes: If you receive a bookmaker_code in an odds feed that isn't in your current mapping, your application should handle it gracefully. Log the unknown code and consider refreshing your catalog.
  • Over-reliance on external data sources: If you're combining data from multiple sources, ensure your mapping strategy can reconcile potential discrepancies. The UK Odds API provides a single, consistent source for its covered bookmakers.
  • Not handling API key security: Hardcoding your API key directly in your script is a security risk. Use environment variables or a secure configuration management system.

Options and Alternatives for Bookmaker Mapping

When you need to map bookmaker brand names to stable codes, you have several approaches. Each comes with its own set of trade-offs in terms of effort, reliability, and coverage. Understanding these alternatives helps you appreciate the value of a dedicated odds API without scraping.

Here's a comparison of common methods:

| Approach | Stability of Bookmaker IDs/Names | Effort to Implement & Maintain | UK Bookmaker Coverage | Notes training.