Examples · Python

How to Find Positive EV Bets With an API (Python)

A bet has positive expected value (+EV) when a sportsbook pays more than the bet is really worth. If the market says a team wins 44% of the time and one book pays +136, betting it repeatedly makes money in the long run.

This tutorial builds a short Python script that lists every +EV bet across US sportsbooks, DFS apps and exchanges, sorted by edge.

Cost: 1 credit per run. The free plan includes 1,000 credits a month. Full project on GitHub.

1. Get the +EV feed

MoneyLine computes edges on its side, so the script makes one call: ml.ev_bets(). Each result names the book, the price, the market's fair win probability (modelProb) and the expected value in percent (evPct).

The fair probability is the average implied probability across sportsbooks, and the API only sets it when at least three sportsbooks price the bet. It ignores any price a book hasn't refreshed in the last 12 hours, so stale lines don't show up as edges.

2. Filter and sort

The script keeps bets at or above --min-ev (2% by default) and sorts the best first. Pass --sportsbooks-only to skip DFS apps and exchanges, where limits and fees differ.

3. Read the output

Each row shows the edge, the price, the fair win chance, the book, the league, the market and the bet. A 4% edge at +136 means that, at the market's fair probability, each $100 bet returns $4 on average.

Edges close quickly. Check the price at the book before you bet, and treat small edges on one bet as noise: +EV pays off over many bets.

The code

ev-finder/ev_finder.py, straight from the repository.

ev_finder.py
"""Find positive expected value (+EV) bets across US sportsbooks with MoneyLine Sports API.

Usage:
    export MONEYLINE_API_KEY=your-key
    python ev_finder.py --league nfl --min-ev 2
"""
import argparse

from moneyline_sports_api import MoneyLine


def fmt_odds(price):
    return f"+{price}" if price > 0 else str(price)


def find_ev_bets(ml, league=None, min_ev=2.0, sportsbooks_only=False):
    """Return +EV bets at or above min_ev percent, best first."""
    source_type = "sportsbook" if sportsbooks_only else None
    bets = ml.ev_bets(league=league, sourceType=source_type, limit=50)  # 1 credit
    picks = [b for b in bets if b["evBet"]["evPct"] >= min_ev]
    return sorted(picks, key=lambda b: b["evBet"]["evPct"], reverse=True)


def main():
    parser = argparse.ArgumentParser(description="Find +EV bets across US sportsbooks.")
    parser.add_argument("--league", help="nfl, nba, mlb, nhl, ncaa_football, ncaa_basketball, soccer_epl, soccer_mls (default: all)")
    parser.add_argument("--min-ev", type=float, default=2.0, help="minimum expected value in percent (default: 2)")
    parser.add_argument("--sportsbooks-only", action="store_true", help="skip DFS apps and exchanges")
    args = parser.parse_args()

    ml = MoneyLine()  # reads MONEYLINE_API_KEY
    picks = find_ev_bets(ml, args.league, args.min_ev, args.sportsbooks_only)
    if not picks:
        print(f"No bets at {args.min_ev}% EV or better right now. Try a lower --min-ev.")
        return

    print(f"{'EV':>6}  {'Odds':>6}  {'Fair win %':>10}  {'Book':<16} {'League':<14} {'Market':<24} Bet")
    for b in picks:
        bet = b["evBet"]
        print(
            f"{bet['evPct']:>5.1f}%  {fmt_odds(bet['odds']):>6}  {bet['modelProb'] * 100:>9.1f}%  "
            f"{bet['bookmaker']:<16} {b['leagueId']:<14} {b['market']:<24} {bet['selection']}"
        )


if __name__ == "__main__":
    main()

Run it

Get a free API key, clone the example, then run:

Terminal
pip install moneyline-sports-api
export MONEYLINE_API_KEY=your-key
python ev_finder.py --league nfl --min-ev 2

More examples