FindMeBet

Methodology

How prices get from a sportsbook into a comparison, what has to be true before we call two prices the same market, and the checks that run before anything is shown. Including the ones we added because we got it wrong.

1. Collection

We read each sportsbook's own public price feed — the same data the site serves to its own front end — on a per-book interval. Books differ enormously in how fast they move and how tolerant they are of being read, so the interval is set per book rather than globally, and backs off automatically when a book starts failing.

Every book is read in English. This is not a presentation choice; it is load-bearing. The same fixture rendered in two languages produces two different team strings, and they will not match each other. A book that only offers a localised feed is read through its English locale or not at all.

We record a price with the time we saw it. Nothing is interpolated, and we do not carry a price forward when a book stops returning it — a stale price is removed rather than held.

2. Which markets we compare

Only markets whose results are mutually exclusive and exhaustive can be compared meaningfully. We currently handle three shapes:

ShapeMeaningExample
home–draw–awaythree-way match result1X2
home–awaytwo-way money lineml
over–undertotals at a stated linetotals:2.5

A book's own label for a market is matched against a per-book rule set that returns accept, reject, or unknown. Two things about that gate matter:

Both of those exist because of a specific failure. A book's board that silently failed to switch sport served a three-way soccer market through a two-way money-line path, which turned the draw price into the away price and produced a convincing 34% price difference that was entirely fictional. The shape check is what now catches that class of bug, and the fail-closed default is what stops the next unseen label doing the same thing.

3. Matching the same fixture across books

This is the hard part, and it is where almost every false result comes from. Books name teams and players inconsistently, and they disagree about start times. A fixture is matched on normalised names plus a kickoff window, and both halves are sport-specific.

Kickoff windows

SportWindowWhy
Default±15 minbooks agree closely on scheduled kickoffs
Tennis±6 hoursorder-of-play times are estimates; we have seen the same match listed hours apart
Esports (slotted)±5 mintournaments run many fixtures back to back; a wide window merges adjacent slots
Esports (real fixtures)±12 hourslistings for a single day's match can be spread very wide

Source of truth: KICKOFF_WINDOW_MS and friends in packages/shared/src/match.ts

The tennis window is the interesting one, because widening it is dangerous in a specific way. A six-hour window admits a player's doubles match, which happens later the same day and reuses the same surname. And a singles pair's two surnames are a strict subset of a doubles pair's four, so a naive token-set comparison scores that as a perfect match. A coin-flip doubles line against a lopsided singles line then looks like an enormous price difference.

So tennis names carry an explicit doubles discriminator: a side formatted as a pair is marked as such during normalisation and can never match a singles side, no matter how well the surnames score.

Name normalisation

Names are reduced before comparison — accents folded, punctuation and sponsor suffixes stripped, common abbreviations unified. Tennis takes a separate path: books render the same player as Surname F., F. Surname, Firstname Surname, or a surname with a country code appended, so a tennis side is reduced to surname tokens plus given-name initials, and doubles pairs are split on their separator.

Fuzzy scores above an accept threshold are taken; scores below a review threshold are rejected outright. The band between them is held for review rather than silently accepted or discarded.

4. Checks before anything is shown

A price difference is not published just because the arithmetic works. Each one is checked for:

Flagged rows are kept, not deleted. That is what makes our published edge distribution possible — we can report how often the checks fire and at what sizes, rather than only reporting what survived them.

5. Known limitations

Stated because a methodology page that lists only strengths is marketing.

6. Corrections

Bugs that produced wrong results, what caused them, and what changed:

What went wrongFix
Quarter handicap read as a full-game money line central market-type gate with an outcome-shape check; fails closed on unknown labels
Tennis doubles matched onto the singles match explicit doubles discriminator during name normalisation
Suspended market whose selections still looked open gate on market-level status, not selection status
Novelty markets ingested as fixtures specials filter at ingest; affected rows purged
Board failed to switch sport, 3-way served as 2-way board-identity verification plus the shape backstop; affected data purged

Each of these produced plausible-looking results before it was caught. That is the honest reason this page exists: the failure mode of a price scanner is not an obvious error, it is a confident wrong answer.