How to normalise odds across bookmakers
OddsRelay · · Updated · 5 min read
Normalising odds across bookmakers is the work of giving one fixture, one market and one selection a single identity, then mapping every book's own labels onto it. Until that is done, two prices for the same outcome cannot sit side by side, and every comparison or oddsmatcher built on them is guessing.
Why don't bookmaker odds line up on their own?
Every book models the same match with its own names, IDs and market structures. The prices are the easy part: convert fractional or American odds to decimal (odds formats) and they compare cleanly. The layers around them drift independently between books.
- Event names differ. One book lists
Man Utd v Man City, anotherManchester United vs Manchester City, a thirdMan. United - Man. City. Kick-off times can be a minute apart, and abbreviations, punctuation and word order all vary. - Selection names differ. The home team, the draw and
Over 2.5 Goalseach appear under slightly different labels.DrawagainstTie, or a player's name spelled two ways, is enough to break a naive join. - Market structures differ. One book's match odds market is another's three-way
1X2. Totals lines, handicap notation and each-way terms are all modelled differently, and the same market can be split at different line values from book to book. - IDs are private. Every book has its own event and selection IDs, and no two share a scheme. There is no common key to join on.
For how a single response is laid out before any of this begins, see the anatomy of an odds API response.
Three matching problems, stacked
That single identity is the join key no book gives you, and you build it top down. Each layer rests on the one above it: a market match is meaningless if the events were wrongly joined.
- Event matching. Decide that book A's
Man Utd v Man Cityand book B'sManchester United vs Manchester Cityare the same fixture, using team identity, competition and kick-off time together. In practice that means cleaning names first (case, punctuation,UtdtoUnited), keeping an alias table per book for what cleaning cannot fix, and accepting a kick-off within a small window. - Market matching. Decide that book A's match odds and book B's
1X2are the same market, and align totals and handicap lines so the same line compares to the same line. - Selection matching. Decide that the home-win price in each maps to the same canonical selection, and that
Over 2.5from one book pairs withOver 2.5from the other, never withUnder.
The output looks simple: every price carries a stable event, market and selection you can group on. That grouping is what a comparison table or an oddsmatcher is built on, and it is the core of how comparison sites use data.
False matches cost more than missed ones
A missed match costs you a row you never see. A false match shows your users a price comparison that is wrong, and your product acts on it. Tune for precision, and let a doubtful pair go unmatched.
A false match looks exactly like a good price
When two prices are wrongly aligned, the gap between them reads as a standout best price or an unusually close back and lay. Loose fuzzy matching produces these constantly.
The first pitfall is false positives: aligning two selections that are not the same. A same-name player in two different fixtures, a totals line read at the wrong value, or a two-way market matched against a three-way one all yield a comparison that is arithmetically valid and factually wrong.
The second is near-duplicate events: one fixture appearing twice with slightly different metadata, or two different fixtures that look almost identical, such as a first-team match and a reserve match. Merge the wrong pair and unrelated prices share a row. Split the right pair and one match is scattered across two IDs, so neither half shows the full market.
Neither is a one-off bug. Fixtures, team names and market layouts change all the time, so matching logic needs continuous maintenance to stay correct. That maintenance is the recurring cost of normalising in-house.
Can a feed do the normalising for you?
Yes, and how much of it depends on the product. In OddsRelay's feed, one fixture is one id on every route: event_id on the six matched boards and id on raw carry the same value, whichever books price the match. The matched boards go further and join every layer. On standard, each outcome of a market lists the bookmakers' back prices with the exchange lay prices beside them.
{
"event_id": "or_evt_917dd44bce05",
"sport_key": "soccer_epl",
"sport_title": "Premier League",
"commence_time": "2026-09-20T14:00:00Z",
"home_team": "Arsenal",
"away_team": "Chelsea",
"markets": [{
"key": "h2h",
"outcomes": [{
"name": "Arsenal",
"back": [
{ "bookmaker": "william_hill", "price": 2.9, "link": null },
{ "bookmaker": "paddy_power", "price": 2.88, "link": null }
],
"lay": [
{ "exchange": "betfair_exchange", "price": 3.0, "available": 175, "link": null }
]
}]
}]
}Comparing William Hill to Paddy Power here is reading two entries in one array. The rows are paired against exchange lay and liquidity-gated. The rating and qualifying loss are simple arithmetic on the pair, and the oddsmatcher widget shows them. In your own code it looks like this:
const outcome = event.markets[0].outcomes[0]; const best = outcome.back.reduce((a, b) => (b.price > a.price ? b : a)); const lay = outcome.lay[0]; const rating = (best.price / lay.price) * 100; // 96.7 before commission
Raw joins less. Each fixture is still one event with every book under its bookmakers list, but each book's markets and outcomes arrive as that book labels them. The event layer is done for you. The market and selection layers stay yours, which is the right trade if you want each book's markets exactly as it prices them. Walking raw covers paging through it.
One caution about the ID. An event_id is opaque and stable across boards, but it is not a durable key: a fixture can be re-keyed once, so treat it as the join key for the board in hand. If you keep history, keep your own fixture record and update its mapping when an id moves.
See the joined rows yourself
The feed covers 140+ bookmakers, 60+ of them live in the UK & Ireland, and the matched boards pair back prices against Betfair, Smarkets, Matchbook and BETDAQ. See live coverage for what is up right now. When the shapes in the API reference fit your join, request access for a key.