Documentation Index Fetch the complete documentation index at: https://docs.odds-api.io/llms.txt
Use this file to discover all available pages before exploring further.
What are Value Bets?
A value bet occurs when the probability of an outcome is greater than what the bookmaker’s odds imply. The Odds-API.io automatically calculates expected value (EV) by comparing individual bookmaker odds against the market average.
How Value Bets Work
Fair odds are calculated from a panel of sharp bookmakers that consistently offer the tightest margins and accept high stakes. These books are stress-tested by professional bettors daily, so their prices reflect genuine market probability better than softer books with padded margins. We use this sharp consensus as the baseline rather than averaging all bookmakers, which would be skewed by recreational pricing.
The API then compares each target bookmaker’s odds against this sharp baseline:
Calculates fair odds from the sharp bookmaker consensus
Compares the target bookmaker’s odds to the fair odds
Identifies opportunities where the bookmaker offers higher odds than the sharp consensus implies
Formula:
Expected Value (EV) = (Fair Probability × Bookmaker Odds) - 1
A positive EV indicates the bookmaker is offering odds above what the sharp market considers fair.
Query Parameters
Parameter Required Description apiKeyYes Your API key bookmakerYes Bookmaker name (e.g. Bet365) sportNo Filter by sport slug (e.g. baseball). Server-side filter — reduces response size and removes the need for client-side filtering. leagueNo Filter by league slug (e.g. usa-mlb). Requires sport to also be set. includeEventDetailsNo Include match info (home, away, league, sport, date) in the response
Fetching Value Bets
Use the /v3/value-bets endpoint to get current value betting opportunities:
const apiKey = process . env . ODDS_API_KEY ;
const bookmaker = 'Bet365' ;
const includeEventDetails = true ;
const response = await fetch (
`https://api.odds-api.io/v3/value-bets?apiKey= ${ apiKey } &bookmaker= ${ bookmaker } &includeEventDetails= ${ includeEventDetails } `
);
const valueBets = await response . json ();
console . log ( valueBets );
Filtering by Sport or League
Filter results server-side so only value bets from the sports or leagues you care about come back. This reduces response size and removes the need for client-side filtering.
curl "https://api.odds-api.io/v3/value-bets?apiKey=YOUR_KEY&bookmaker=Bet365&sport=baseball"
Validation rules:
Providing league without sport returns 400.
Unknown sport slug returns 400.
Unknown league for a valid sport returns 404.
[
{
"id" : "vb_123456_bet365_home" ,
"eventId" : 123456 ,
"bookmaker" : "Bet365" ,
"market" : {
"name" : "ML" ,
"home" : "2.10" ,
"draw" : "3.40" ,
"away" : "3.20" ,
"hdp" : null ,
"max" : null
},
"betSide" : "home" ,
"expectedValue" : 0.0523 ,
"expectedValueUpdatedAt" : "2025-10-04T10:30:00Z" ,
"bookmakerOdds" : {
"home" : "2.10" ,
"draw" : "3.40" ,
"away" : "3.20" ,
"href" : "https://bet365.com/..."
},
"event" : {
"home" : "Manchester United" ,
"away" : "Liverpool" ,
"date" : "2025-10-15T15:00:00Z" ,
"sport" : "Football" ,
"league" : "England - Premier League"
}
}
]
Understanding the Response
Field Description expectedValueThe calculated EV (positive means value) betSideWhich outcome has value (home, draw, away, over, under, etc.) marketMarket odds used for comparison bookmakerOddsCurrent odds at the bookmaker eventMatch details (when includeEventDetails=true)
Filtering Value Bets
Filter value bets to find the most profitable opportunities:
function filterValueBets ( valueBets , minEV = 0.03 ) {
return valueBets
. filter ( bet => bet . expectedValue >= minEV )
. sort (( a , b ) => b . expectedValue - a . expectedValue );
}
// Get value bets with at least 3% expected value
const topValueBets = filterValueBets ( valueBets , 0.03 );
topValueBets . forEach ( bet => {
const evPercent = ( bet . expectedValue * 100 ). toFixed ( 2 );
console . log ( ` ${ bet . event . home } vs ${ bet . event . away } ` );
console . log ( `Bet on: ${ bet . betSide } ` );
console . log ( `EV: ${ evPercent } %` );
console . log ( `Odds: ${ bet . bookmakerOdds [ bet . betSide ] } ` );
console . log ( '---' );
});
Real-Time Value Bet Monitoring
Value bets are updated every 5 seconds . Here’s how to build a monitoring system:
async function monitorValueBets ( bookmaker , minEV = 0.03 ) {
const apiKey = process . env . ODDS_API_KEY ;
async function fetchAndProcess () {
try {
const response = await fetch (
`https://api.odds-api.io/v3/value-bets?apiKey= ${ apiKey } &bookmaker= ${ bookmaker } &includeEventDetails=true`
);
const valueBets = await response . json ();
const filtered = valueBets . filter ( bet => bet . expectedValue >= minEV );
filtered . forEach ( bet => {
notifyUser ( bet ); // Send notification to users
logBet ( bet ); // Log for analytics
});
} catch ( error ) {
console . error ( 'Error fetching value bets:' , error );
}
}
// Initial fetch
await fetchAndProcess ();
// Poll every 5 seconds
setInterval ( fetchAndProcess , 5000 );
}
// Start monitoring
monitorValueBets ( 'Bet365' , 0.03 );
Multi-Bookmaker Strategy
Monitor value bets across multiple bookmakers:
const bookmakers = [ 'Bet365' , 'Unibet' , 'SingBet' , 'William Hill' ];
async function getAllValueBets ( minEV = 0.03 ) {
const apiKey = process . env . ODDS_API_KEY ;
const promises = bookmakers . map ( bookmaker =>
fetch (
`https://api.odds-api.io/v3/value-bets?apiKey= ${ apiKey } &bookmaker= ${ bookmaker } &includeEventDetails=true`
). then ( res => res . json ())
);
const results = await Promise . all ( promises );
// Flatten and filter
const allValueBets = results
. flat ()
. filter ( bet => bet . expectedValue >= minEV )
. sort (( a , b ) => b . expectedValue - a . expectedValue );
return allValueBets ;
}
const topBets = await getAllValueBets ( 0.03 );
Building a Value Bet Alert System
class ValueBetAlerter {
constructor ( apiKey , minEV = 0.03 ) {
this . apiKey = apiKey ;
this . minEV = minEV ;
this . seenBets = new Set ();
}
async checkForNewValueBets ( bookmaker ) {
const response = await fetch (
`https://api.odds-api.io/v3/value-bets?apiKey= ${ this . apiKey } &bookmaker= ${ bookmaker } &includeEventDetails=true`
);
const valueBets = await response . json ();
const newBets = valueBets . filter ( bet => {
if ( bet . expectedValue < this . minEV ) return false ;
if ( this . seenBets . has ( bet . id )) return false ;
this . seenBets . add ( bet . id );
return true ;
});
return newBets ;
}
async sendAlert ( bet ) {
const message = `
🎯 Value Bet Alert!
${ bet . event . home } vs ${ bet . event . away }
League: ${ bet . event . league }
Sport: ${ bet . event . sport }
Market: ${ bet . market . name }
Bet on: ${ bet . betSide }
Odds: ${ bet . bookmakerOdds [ bet . betSide ] }
Expected Value: ${ ( bet . expectedValue * 100 ). toFixed ( 2 ) } %
Bookmaker: ${ bet . bookmaker }
Place bet: ${ bet . bookmakerOdds . href }
` ;
// Send to your notification system
// (Email, SMS, Discord, Telegram, etc.)
console . log ( message );
}
async monitor ( bookmakers ) {
for ( const bookmaker of bookmakers ) {
const newBets = await this . checkForNewValueBets ( bookmaker );
newBets . forEach ( bet => this . sendAlert ( bet ));
}
// Check every 5 seconds
setTimeout (() => this . monitor ( bookmakers ), 5000 );
}
}
// Usage
const alerter = new ValueBetAlerter ( process . env . ODDS_API_KEY , 0.03 );
alerter . monitor ([ 'Bet365' , 'Unibet' , 'SingBet' ]);
Best Practices
Set Realistic EV Thresholds
Start with a minimum EV of 3-5%. Lower thresholds will generate more alerts but may include less significant opportunities.
Monitor Multiple Bookmakers
Different bookmakers have different inefficiencies. Monitor several bookmakers to maximize opportunities.
Value bets can disappear quickly as bookmakers adjust odds. Implement fast notification systems.
Log all value bets and outcomes to analyze the accuracy of the expected value calculations over time.
Use the Kelly Criterion or similar methods to determine optimal stake sizes based on expected value.
Kelly Criterion Example
Calculate optimal stake using the Kelly Criterion:
function calculateKellyStake ( probability , odds , bankroll , kellyFraction = 0.25 ) {
// Kelly = (probability * odds - 1) / (odds - 1)
const kelly = ( probability * odds - 1 ) / ( odds - 1 );
// Use fractional Kelly for safety (e.g., 25% of full Kelly)
const fractionalKelly = kelly * kellyFraction ;
// Calculate stake
const stake = bankroll * fractionalKelly ;
return Math . max ( 0 , stake ); // Don't bet if negative
}
// Example
const bet = valueBets [ 0 ];
const impliedProb = 1 / parseFloat ( bet . bookmakerOdds [ bet . betSide ]);
const trueProbability = impliedProb * ( 1 + bet . expectedValue );
const odds = parseFloat ( bet . bookmakerOdds [ bet . betSide ]);
const bankroll = 1000 ;
const stake = calculateKellyStake ( trueProbability , odds , bankroll );
console . log ( `Recommended stake: $ ${ stake . toFixed ( 2 ) } ` );
Limitations & Considerations
Value bets are theoretical - actual profitability depends on many factors
Bookmakers may limit accounts that consistently find value
Odds can change between viewing and placing a bet
Not all value bets will win (that’s the nature of probability)
Next Steps
Fetching Odds Learn more about working with odds data
Best Practices Optimize your API usage