DEV Community

SkipSeek
SkipSeek

Posted on

Bookmaker odds lie by 5-10%. De-vig them in 10 lines.

Take any soccer match. Convert the three moneyline odds to implied probabilities and add them up. You won't get 100%. You'll get 105-110%.

Home 1.90  → 1/1.90 = 52.6%
Draw 3.60  → 1/3.60 = 27.8%
Away 4.20  → 1/4.20 = 23.8%
                Sum = 104.2%
Enter fullscreen mode Exit fullscreen mode

That extra 4.2% is the bookmaker's margin — the "vig." It's not a prediction; it's a fee, smeared invisibly across every outcome. If you publish raw implied probabilities in your app, your content quietly inherits it: every team looks a few points more likely to win than the market actually believes.

De-vig in 10 lines

The simplest fix is proportional normalization — divide each implied probability by the sum:

function devig(odds) {
  // odds: { home: 1.90, draw: 3.60, away: 4.20 }
  const implied = Object.fromEntries(
    Object.entries(odds).map(([k, o]) => [k, 1 / o])
  );
  const sum = Object.values(implied).reduce((a, b) => a + b, 0);
  return Object.fromEntries(
    Object.entries(implied).map(([k, p]) => [k, p / sum])
  );
}

devig({ home: 1.90, draw: 3.60, away: 4.20 });
// → { home: 0.505, draw: 0.267, away: 0.228 }  — sums to exactly 1
Enter fullscreen mode Exit fullscreen mode

Now the probabilities are the market's actual opinion, margin removed.

The part that's not 10 lines

One bookmaker's de-vigged line is still one bookmaker's opinion. For a stable number you want the consensus: survey many books, de-vig each, average them — continuously, across every fixture, in every sport you cover. That's a pipeline, not a snippet.

I run that pipeline at SkipOdds: 69+ bookmakers, 13 sports (soccer, NFL, NBA, MLB, NHL, tennis, golf, cricket, rugby, MMA, boxing, college football and basketball), averaged and de-vigged so every response sums to exactly 100%. There's a free demo key you can hit right now:

curl -H "x-api-key: skipodds-demo-2026" \
  "https://skipodds.com/v1/fixtures?limit=3"
Enter fullscreen mode Exit fullscreen mode
{
  "fixtures": [{
    "home_team": "France",
    "away_team": "England",
    "skipodds": {
      "home": 0.501, "draw": 0.247, "away": 0.252,
      "books_surveyed": 69,
      "margin_removed": 0.05
    }
  }]
}
Enter fullscreen mode Exit fullscreen mode

The responses never name a bookmaker — you get the cleaned consensus, so there's nothing gambling-adjacent to moderate if you're publishing to a general audience.

Bonus: your AI agent can use it too

The same API is exposed as a remote MCP server at https://skipodds.com/mcp (com.skipodds/skipodds in the official MCP registry). Point Claude, Cursor, or any MCP client at it and ask "what are the fair odds for the next big fight" — no key required for the demo quota.

Docs and the OpenAPI spec: skipodds.com/docs · openapi.json

Free tier is 100 requests/day with attribution. If you build something with it, I'd genuinely like to see it.

Top comments (0)