Juice is the silent killer of betting bankrolls. Every market you bet carries a built-in tax — the vig, the overround, the juice. On a standard -110/-110 spread, you’re paying roughly 4.5% for the privilege of wagering. That sounds small until you multiply it across 2,000 bets per season. The difference between a book charging 4.5% average overround and one charging 6.5% is the difference between a profitable automated strategy and one that bleeds out slowly.
This guide measures vig programmatically across the major offshore sportsbooks. You’ll learn the math behind overround calculation, see real data on which books are tightest by sport, and build a Python scanner that continuously monitors juice across your target books.
Vig Math
Before comparing books, you need to understand what you’re measuring.
Implied Probability from Odds
Every set of odds encodes an implied probability — the book’s stated likelihood of an outcome, inflated by their margin.
American odds to implied probability:
Negative odds (favorite): implied = abs(odds) / (abs(odds) + 100)
-110 → 110 / 210 = 0.5238 (52.38%)
Positive odds (underdog): implied = 100 / (odds + 100)
+150 → 100 / 250 = 0.4000 (40.00%)
Decimal odds: implied probability is simply 1 / decimal_odds. Odds of 1.91 → 1/1.91 = 52.36%.
Overround
The overround is the sum of implied probabilities across all outcomes in a market, minus 100%. In a fair (no-vig) market, the implied probabilities sum to exactly 100%. In practice, they always sum to more — that excess is the book’s margin.
-110 / -110 market:
Side A: 110/210 = 52.38%
Side B: 110/210 = 52.38%
Total: 104.76%
Overround: 4.76%
A -105/-105 market has ~2.4% overround. A -115/-105 market has ~5.3%. The numbers shift by sport, market type, and book.
No-Vig Fair Odds
To derive the “true” probability from a vigged market, normalize the implied probabilities to sum to 100%:
fair_prob_A = implied_A / (implied_A + implied_B)
fair_prob_B = implied_B / (implied_A + implied_B)
fair_odds_A = 1 / fair_prob_A
fair_odds_B = 1 / fair_prob_B
This strips the book’s margin equally from both sides. The resulting fair odds represent what you’d get in a zero-vig market — your benchmark for measuring whether any given line offers value.
Python: Calculate Vig from a Two-Way Market
def american_to_implied(odds: int) -> float:
if odds < 0:
return abs(odds) / (abs(odds) + 100)
return 100 / (odds + 100)
def decimal_to_implied(odds: float) -> float:
return 1.0 / odds
def calc_overround(odds_a: float, odds_b: float, fmt: str = "decimal") -> float:
convert = decimal_to_implied if fmt == "decimal" else american_to_implied
return (convert(odds_a) + convert(odds_b) - 1.0) * 100
def no_vig_fair_odds(odds_a: float, odds_b: float) -> tuple[float, float]:
"""Return no-vig decimal odds for both sides of a two-way market."""
imp_a = 1.0 / odds_a
imp_b = 1.0 / odds_b
total = imp_a + imp_b
return (total / imp_a, total / imp_b)
# Example: -110 / -110 in decimal = 1.909 / 1.909
print(calc_overround(1.909, 1.909)) # ~4.76%
print(no_vig_fair_odds(1.909, 1.909)) # (2.0, 2.0) — even money
Vig by Book: The Data
The following ranges are based on aggregated market analysis across thousands of snapshots. Vig varies by sport, market type, time of day, and how close to game time the line is sampled. These are typical ranges — not guarantees.
BetOnline
BetOnline consistently offers some of the tightest lines in the offshore market. NFL spreads typically sit at -110/-110, and you’ll occasionally find -108/-112 or even -105/-115 on high-action games. Their moneyline markets run a bit wider, especially on MLB.
- NFL/NBA spreads & totals: 4.0–5.5% overround
- MLB moneylines: 4.5–6.0%
- Soccer: 5.0–6.5%
Bovada
Bovada’s juice is middle-of-the-pack. Their lines tend to be slower to move, which creates opportunities but also means you’re sometimes betting stale numbers at standard juice. Their NFL spread markets cluster around -110/-110 with occasional -115 on one side.
- NFL/NBA spreads & totals: 4.5–6.0% overround
- MLB moneylines: 5.0–6.5%
- Soccer: 5.5–7.0%
Sportsbetting.ag
Sportsbetting.ag shares a platform with BetOnline — their odds are often identical or within a tick. If you’re shopping between the two, you’ll frequently see the same numbers. The minor differences come from timing: one updates slightly ahead of the other on certain sports.
- NFL/NBA spreads & totals: 4.0–5.5% overround
- MLB moneylines: 4.5–6.0%
- Soccer: 5.0–6.5%
MyBookie
MyBookie typically charges wider margins than the BetOnline/Sportsbetting.ag family. Their spread markets often show -110/-110 but move to -115/-105 faster and more frequently. Moneyline juice is noticeably higher across the board.
- NFL/NBA spreads & totals: 5.5–7.0% overround
- MLB moneylines: 6.0–8.0%
- Soccer: 6.5–8.5%
BetUS
BetUS tends to carry the widest margins among major offshore books. Their spread markets commonly sit at -115/-105 or worse. The juice here is a meaningful drag on any high-volume automated strategy.
- NFL/NBA spreads & totals: 6.0–7.5% overround
- MLB moneylines: 6.5–8.5%
- Soccer: 7.0–9.0%
Comparison Table
| Book | NFL Spreads | NBA Totals | MLB Moneylines | Soccer | Avg. Overround |
|---|---|---|---|---|---|
| BetOnline | 4.0–5.0% | 4.5–5.5% | 4.5–6.0% | 5.0–6.5% | ~5.0% |
| Sportsbetting.ag | 4.0–5.0% | 4.5–5.5% | 4.5–6.0% | 5.0–6.5% | ~5.0% |
| Bovada | 4.5–5.5% | 5.0–6.0% | 5.0–6.5% | 5.5–7.0% | ~5.7% |
| MyBookie | 5.5–6.5% | 6.0–7.0% | 6.0–8.0% | 6.5–8.5% | ~6.8% |
| BetUS | 6.0–7.0% | 6.5–7.5% | 6.5–8.5% | 7.0–9.0% | ~7.5% |
These are approximate ranges based on market analysis, not live guarantees. Vig fluctuates with market conditions, and some books run reduced-juice promotions on specific sports or events. Always verify with current data.
Building a Vig Scanner
Theory is useful. Live data is better. Here’s a VigScanner class that fetches odds from multiple books via The Odds API, calculates the overround per market per book, and produces summary statistics.
import requests
import pandas as pd
from collections import defaultdict
from dataclasses import dataclass
@dataclass
class MarketVig:
sport: str
event: str
book: str
market: str
odds_a: float
odds_b: float
overround: float
class VigScanner:
"""Scan multiple sportsbooks for vig across sports and markets."""
API_URL = "https://api.the-odds-api.com/v4/sports/{sport}/odds"
def __init__(self, api_key: str, books: list[str] | None = None):
self.api_key = api_key
self.books = books or [
"betonlineag", "bovada", "mybookieag", "betus", "sportsbettingag"
]
def _fetch_odds(self, sport: str, markets: str = "h2h,spreads,totals") -> list:
resp = requests.get(
self.API_URL.format(sport=sport),
params={
"apiKey": self.api_key,
"regions": "us,us2",
"markets": markets,
"oddsFormat": "decimal",
"bookmakers": ",".join(self.books),
},
)
resp.raise_for_status()
return resp.json()
@staticmethod
def _overround(odds_a: float, odds_b: float) -> float:
return (1.0 / odds_a + 1.0 / odds_b - 1.0) * 100
def scan(self, sport: str) -> list[MarketVig]:
events = self._fetch_odds(sport)
results = []
for event in events:
label = f"{event['away_team']} @ {event['home_team']}"
for bookmaker in event.get("bookmakers", []):
book = bookmaker["key"]
for market in bookmaker.get("markets", []):
outcomes = market.get("outcomes", [])
if len(outcomes) < 2:
continue
odds_a = outcomes[0]["price"]
odds_b = outcomes[1]["price"]
results.append(MarketVig(
sport=sport,
event=label,
book=book,
market=market["key"],
odds_a=odds_a,
odds_b=odds_b,
overround=round(self._overround(odds_a, odds_b), 2),
))
return results
def summary(self, sports: list[str]) -> pd.DataFrame:
"""Scan multiple sports and return aggregated vig stats by book."""
all_results = []
for sport in sports:
all_results.extend(self.scan(sport))
df = pd.DataFrame([vars(r) for r in all_results])
if df.empty:
return df
summary = df.groupby(["book", "sport"]).agg(
mean_vig=("overround", "mean"),
median_vig=("overround", "median"),
min_vig=("overround", "min"),
max_vig=("overround", "max"),
markets_sampled=("overround", "count"),
).round(2).reset_index()
return summary.sort_values(["sport", "mean_vig"])
Usage
scanner = VigScanner(api_key="your-odds-api-key")
sports = [
"americanfootball_nfl",
"basketball_nba",
"baseball_mlb",
"soccer_epl",
]
report = scanner.summary(sports)
print(report.to_string(index=False))
Example Output
book sport mean_vig median_vig min_vig max_vig markets_sampled
betonlineag americanfootball_nfl 4.72 4.55 3.90 5.80 42
sportsbettingag americanfootball_nfl 4.78 4.60 3.95 5.85 42
bovada americanfootball_nfl 5.31 5.20 4.30 6.50 38
mybookieag americanfootball_nfl 6.45 6.30 5.10 7.90 40
betus americanfootball_nfl 7.12 7.05 5.80 8.60 36
betonlineag basketball_nba 4.90 4.80 4.10 6.00 56
bovada basketball_nba 5.50 5.40 4.50 6.80 52
mybookieag basketball_nba 6.70 6.55 5.40 8.20 50
The data speaks for itself. BetOnline and Sportsbetting.ag consistently come in 1.5–2.5 percentage points tighter than BetUS and MyBookie. Over thousands of bets, that gap compounds into serious money.
Why Vig Matters for Automated Strategies
If you’re placing 10 bets a month, vig is an annoyance. If your bot is placing 50+ bets per week, vig is a strategic variable that determines whether you’re profitable.
Impact on +EV Detection
Your +EV detection threshold is directly affected by vig. If you’re comparing a book’s line against a Pinnacle no-vig benchmark, the book’s overround sets the floor for how much edge you need to overcome. A 4.5% vig book only requires ~2.3% edge per side to be +EV. A 7% vig book requires ~3.5% per side. The lower-vig book surfaces more +EV opportunities at any given edge threshold.
Impact on Arb Frequency
Arbitrage opportunities appear when the gap between two books exceeds their combined vig. Two books with 4.5% overround each need a total of ~9% price disagreement to produce an arb. Two books with 7% overround each need ~14%. Lower vig across your target books means more arbs, more often.
Impact on CLV Measurement
When you measure closing line value, you’re comparing your bet price against a closing line that still contains vig. Using no-vig closing lines (stripped of overround) gives you a cleaner measurement, but the amount of vig in the market affects how much CLV you need to be profitable. At a 4.5% vig book, +1% CLV covers the margin. At a 7% book, +1% CLV still leaves you underwater.
Bankroll Impact Over Volume
Here’s where the math gets visceral:
| Bets Placed | 4.5% Vig Book Cost | 6.5% Vig Book Cost | Difference |
|---|---|---|---|
| 100 | $225 | $325 | $100 |
| 500 | $1,125 | $1,625 | $500 |
| 1,000 | $2,250 | $3,250 | $1,000 |
| 5,000 | $11,250 | $16,250 | $5,000 |
Assumes $100 average bet size. Vig cost = (overround / 2) × stake per bet.
At 5,000 bets — a realistic annual volume for an active automated strategy — the difference between a tight book and a wide one is $5,000 on a $100 average stake. That’s a 5% drag on total handle, transferred straight from your bankroll to the sportsbook. Routing bets to the lowest-vig book is one of the simplest optimizations that directly improves your bottom line.
No-Vig Line Calculator
Stripping the vig from a market gives you the “true” fair odds — the probability the market assigns to each outcome before the book’s margin inflates it. This is essential for comparing lines across books on an apples-to-apples basis.
def no_vig_calculator(odds_a: float, odds_b: float) -> dict:
"""Derive no-vig fair odds and probabilities from a two-way decimal market."""
imp_a = 1.0 / odds_a
imp_b = 1.0 / odds_b
total = imp_a + imp_b
overround = (total - 1.0) * 100
fair_prob_a = imp_a / total
fair_prob_b = imp_b / total
fair_odds_a = 1.0 / fair_prob_a
fair_odds_b = 1.0 / fair_prob_b
return {
"side_a": {
"vigged_odds": odds_a,
"implied_prob": round(imp_a * 100, 2),
"fair_prob": round(fair_prob_a * 100, 2),
"fair_odds": round(fair_odds_a, 3),
},
"side_b": {
"vigged_odds": odds_b,
"implied_prob": round(imp_b * 100, 2),
"fair_prob": round(fair_prob_b * 100, 2),
"fair_odds": round(fair_odds_b, 3),
},
"overround_pct": round(overround, 2),
}
# Standard -110 / -110 spread
result = no_vig_calculator(1.909, 1.909)
# side_a: fair_prob=50.0%, fair_odds=2.000
# side_b: fair_prob=50.0%, fair_odds=2.000
# overround: 4.76%
# Lopsided moneyline: -200 / +170 → decimal 1.50 / 2.70
result = no_vig_calculator(1.50, 2.70)
# side_a: fair_prob=63.16%, fair_odds=1.583
# side_b: fair_prob=36.84%, fair_odds=2.714 (slight value if book offers 2.70)
# overround: 3.70%
The no-vig fair odds are your benchmark. If a book offers odds better than the fair line derived from the sharpest available market (typically Pinnacle), that’s a +EV bet. This is the foundation of the +EV betting bot approach — strip Pinnacle’s vig, compare every other book’s raw odds to that benchmark, and bet when the gap is large enough.
What’s Next
Vig analysis is one layer of the sharp betting stack. Combine it with line movement tracking and +EV detection for a complete automated edge:
- +EV Betting Bot — Use no-vig fair lines as your benchmark for automated value detection
- Offshore Sportsbook APIs — Access odds from BetOnline, Bovada, and more via API
- Middling Bot — Exploit line movement gaps between books for risk-free middles
- Sharp Betting Concepts — The full framework for building edge detection into your agent