How to Find Arbitrage Bets: The Math, Examples and Data
The arbitrage condition, worked two-way and three-way examples, scanning odds data for arbs with /v1/best-lines or the MCP find_arbitrage tool, stake sizing, and the risks that close arbs before you get there.
An arbitrage bet, or arb, is a set of bets on every outcome of one market, placed at different books, priced so that the combined return is the same whichever outcome wins and larger than the total staked. These arbitrage opportunities exist only when books disagree enough on a price, and they rarely last. Learning how to find arbitrage bets is mostly about two things: a simple inequality, and data fast and wide enough to test it across many books at once.
This guide covers the math with two- and three-way examples, how to scan a whole league with the PreciseAPI feed, how to size stakes, and the practical risks that turn a paper arb into a loss. It explains the mechanics; it is not betting advice, and nothing here guarantees a profit.
The arbitrage condition
Every price implies a probability. In decimal odds it is simply 1 / decimal. A single book's prices on all sides of a market add up to more than 100%, because the book builds its margin into them. A -110 / -110 spread, for example, sums to 52.38% + 52.38% = 104.76%.
Arbitrage betting looks at the best price on each side across different books instead. If those best prices sum to less than 100%, an arb exists:
sum = 1/d1 + 1/d2 (+ 1/d3 for three-way markets)
arb exists when sum < 1
arb return = 1 / sum - 1
The arb return is a percentage of the total staked. It is usually small, because books' prices rarely drift far apart for long, and it only holds if every leg is placed at the quoted price.
A two-way example
Suppose two books disagree on an NBA moneyline:
| Side | Book | American | Decimal | Implied |
|---|---|---|---|---|
| Home | Book A | +105 | 2.050 | 48.78% |
| Away | Book B | +100 | 2.000 | 50.00% |
| Sum | 98.78% |
The sum is under 100%, so the return is 1 / 0.9878 - 1 = 1.235%. With $1,000 to split, the stakes are proportional to each side's implied probability:
- Home at Book A: $1,000 × 0.4878 / 0.9878 = $493.83, which returns $493.83 × 2.05 = $1,012.35
- Away at Book B: $1,000 × 0.5000 / 0.9878 = $506.17, which returns $506.17 × 2.00 = $1,012.35
Either way the payout is $1,012.35, a $12.35 profit on $1,000. Compare that with a single book's -110 / -110 market, where the same split loses $45.45 whichever side wins.
A three-way example
Soccer moneylines have three outcomes (home, draw, away), so an arb needs three legs, usually at three books:
| Outcome | Book | Decimal | Implied |
|---|---|---|---|
| Home | Book A | 2.50 | 40.00% |
| Draw | Book B | 3.50 | 28.57% |
| Away | Book C | 3.30 | 30.30% |
| Sum | 98.87% |
The return is 1 / 0.98874 - 1 = 1.138%. On $1,000 the stakes are $404.55, $288.97 and $306.48, and every outcome pays about $1,011.38. Three legs means three chances for a price to move before you get it, which matters later in this post.
How to find arbitrage bets with odds data
Checking two apps by hand will almost never turn up an arb. They come from the edges of a large board: one book slow to move after news, one exchange with a stale order, one prop line out of step. Finding them means comparing every outcome across every book you can use, many times a minute. That is the job of an arb finder, and you can build one from the feed in a few dozen lines.
PreciseAPI does not have a /v1/arbitrage endpoint. Arbs are computed from REST data, or found for you by the MCP tool described below.
Step 1: get the best price per outcome
/v1/best-lines already does the hard part. For every comparable market it returns the best price on each side and every book offering it. It groups books by line, so home -3 and home -3.5 are never mixed, skips suspended markets, excludes DFS pick'em apps, and needs at least two books quoting. It costs 3 credits per request, however many games come back.
curl "https://api.preciseapi.com/v1/best-lines?league=nba&markets=main&format=decimal&books=draftkings,fanduel,betmgm,caesars,fanatics,circa&max_source_age_ms=60000" \
-H "Authorization: Bearer $PRECISEAPI_KEY"
books= limits the comparison to the books you can actually use, and max_source_age_ms drops any quote older than a minute, so a stale price never shows up as an arb.
Step 2: test the condition
With decimal prices, the check is one line per market:
const API = 'https://api.preciseapi.com/v1';
const headers = { Authorization: `Bearer ${process.env.PRECISEAPI_KEY}` };
const BOOKS = ['draftkings', 'fanduel', 'betmgm', 'caesars', 'fanatics', 'circa'];
export async function findArbs(league, total = 1000) {
const qs = new URLSearchParams({ league, markets: 'main', format: 'decimal', books: BOOKS.join(','), max_source_age_ms: '60000' });
const res = await fetch(`${API}/best-lines?${qs}`, { headers });
if (!res.ok) throw new Error(`best-lines failed: ${res.status}`);
const { data } = await res.json();
const arbs = [];
for (const event of data) {
for (const m of event.markets) {
const sum = m.outcomes.reduce((s, o) => s + 1 / o.best_price, 0);
if (sum >= 1) continue;
arbs.push({
game: `${event.away.name} @ ${event.home.name}`,
market: m.key,
period: m.period,
line: m.line,
return_pct: +((1 / sum - 1) * 100).toFixed(2),
legs: m.outcomes.map((o) => ({
side: o.name,
point: o.point,
price: o.best_price,
books: o.best_books,
stake: +((total / o.best_price) / sum).toFixed(2),
})),
});
}
}
return arbs.sort((a, b) => b.return_pct - a.return_pct);
}
Because best_books lists every book tied at the best price, you can choose the leg's book by your own preference, for example the one where your account has room.
Step 3: or ask the MCP server
If you use Claude, ChatGPT or another AI client, the PreciseAPI MCP server has a find_arbitrage tool that does all of the above in one call. It scans a league's upcoming games, combines only identical lines, requires the legs to span at least two books, and returns each leg's book, price and stake for a total you choose, with the payout and profit. Options include books (only the books you use), markets (main or props), min_margin_pct (a negative value also shows near-arbs) and total_stake. Each call costs 3 credits, like the REST endpoint it reads.
A prompt as plain as "any arbitrage on MLB totals between DraftKings, FanDuel and Circa?" is enough. The odds API MCP guide covers setup and the full tool list.
Stake sizing
The stake on each leg is the total multiplied by that leg's share of the implied-probability sum:
stake_i = total × (1 / d_i) / sum
In practice you will round stakes, and books may cap them. Rounding the two-way example to $494 and $506 gives payouts of $1,012.70 and $1,012.00, so the smallest profit falls slightly to $12.00. Always recompute the worst-case payout after rounding. Some bettors also bias stakes toward one leg on purpose, accepting a smaller profit on one outcome for a larger one on the other, which is no longer a pure arb.
The free arbitrage calculator checks whether a set of prices is an arb and splits any total across two or three legs, including after you round.
The risks that close arbs
Arbs are sometimes marketed as if nothing can go wrong. The math is exact; the execution is not. These are the ways a paper arb goes wrong.
Prices move between legs
You place the first leg, and before you place the second the other book moves. Now you hold one side at a good price and the other at a worse one, or not at all. Arbs often exist precisely because one book has not yet reacted to a move, so the window can be short. Placing the slower or more limited book first, and re-checking prices immediately before each leg, reduces but does not remove this risk.
Palps and voids
Books' terms usually let them void bets placed at a "palpable error" price, an obvious mistake such as a swapped line. If one leg of an arb is voided after the other has settled, you are left with an unhedged bet. The more an arb looks too good to be true, the more likely this is.
Limits and account restrictions
Books, especially retail ones, commonly limit the stakes of customers whose betting pattern looks professional, and a history of arbitrage betting is an easy pattern to spot. A limit can cut a leg to a fraction of the stake you need, which breaks the hedge.
Rules mismatches
Two books can settle the same-looking market differently: overtime included or not, a tennis retirement, a player prop when the player doesn't start, a game postponed or moved. An arb across books with different rules can lose on both legs.
Stale data
Your own data has latency too. A price seen ten seconds ago may already be gone. Filter by updated_at or max_source_age_ms, and treat every result as an observation that has to be confirmed at the book.
Where arbs tend to appear
No dataset can promise arbs, but part of knowing how to find arbitrage bets is knowing where to look, and the structure of the market points the way. They tend to appear right after news or a sharp move, when some books have reacted and others haven't; between books on different platforms, since books sharing one platform usually match each other; on exchanges and prediction markets, where a thin order book can sit away from the sportsbook price; and on player props and less popular markets, where fewer traders watch each line. The how sportsbooks get odds post explains why books move at different speeds.
Plans and polling cost
Knowing how to find arbitrage bets in code is half the job; the other half is keeping the data fresh. An arb scan is a polling job, so cost depends on how often you call. One /v1/best-lines call every 30 seconds is 6 credits a minute, about 259,200 a month, which is more than the 150,000 credits on Edge, so frequent scanning fits the unlimited Sharp plan. Live in-play prices and the WebSocket stream are on Syndicate; the stream costs 1 credit per connection-minute and lets you recompute best prices on every change. See pricing for the full matrix, and the arbitrage API page for how the pieces fit together.
Frequently asked questions
Does PreciseAPI have an arbitrage endpoint?
No. There is no /v1/arbitrage endpoint. You compute arbs from /v1/best-lines or /v1/odds, as shown above, or use the find_arbitrage tool on the MCP server, which reads the same best-lines data and returns legs and stakes.
How big is a typical arbitrage margin?
It depends entirely on the prices at the moment, and the formula is 1 / sum - 1. Because books' prices rarely stay far apart, arbs that do appear are usually small and short-lived. Treat any large margin as a likely stale price or palpable error until confirmed.
Can I find arbitrage on player props?
Yes. Pass player_* market keys to /v1/best-lines, or markets: "props" to find_arbitrage. Player props are included on every paid plan. DFS pick'em apps are excluded from both, since they pay fixed multipliers rather than per-selection prices.
Why did an arb disappear before I could bet it?
Usually because a book moved its price, often the slower book catching up with the market. Arbs close quickly, which is why fresh data and re-checking every price at the book before placing each leg matter.