sports-betting: a scikit-learn wrapper for value-bet backtesting, with an execution layer that spends real money
Collection of sports betting AI tools.
At a glance
- What is it?
- georgedouzas/sports-betting is a Python library that pairs pluggable statistics and odds sources with a bettor that wraps any scikit-learn estimator. Its most consequential feature is also its riskiest: an execution path that places bets through bookmaker APIs or by driving a bookmaker's website.
- Who is it for?
- Adopt it if you already work in scikit-learn, you want the choice of statistics and odds source to be explicit in your code, and you are prepared to treat the execution layer as a separate, higher-risk decision. Do not adopt it if your goal is a turnkey tipster service, or if you cannot afford to re-extract data after a paid odds feed has been billed.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 50 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem: a modelling pipeline whose data provenance is explicit
Most sports betting code starts as a notebook with a hardcoded CSV. The odds come from somewhere, the results come from somewhere else, and six months later nobody can say which feed produced which column. sports-betting attacks that specific problem by making the two inputs separate objects. The README describes a dataloader as being built from a statistics source and an odds source, and states the reason plainly: you choose both, so you always know where your data came from. That is the whole design thesis. The library is for engineers who already have a modelling workflow and want the data plumbing and the backtest harness to be a library rather than a folder of scripts. It is not aimed at someone who wants picks delivered to a phone.
Two nouns: dataloaders and bettors
The README splits the library into two parts. A dataloader downloads data and shapes it for modelling; a bettor backtests a betting strategy and predicts value bets on upcoming events. The bettor wraps any scikit-learn estimator, which is the load-bearing sentence in the whole project. Nothing in the library forces you into a particular model family. If you have a gradient boosting classifier you already trust, it becomes a bettor input rather than a rewrite. The trade-off is that the library takes no position on model quality. It gives you the harness and the train/fixtures split, and the estimator you hand it determines whether the backtest means anything. The README's Python example shows the shape of that split directly: extract_train_data returns X_train, Y_train and O_train, while extract_fixtures_data returns X_fix, O_fix and discards the labels. The odds columns are carried through both calls, which is what lets a backtest score a strategy in money terms rather than accuracy terms.
Getting it running: pip, extras and one Playwright command
Installation is a plain PyPI install: pip install sports-betting. The MCP server that lets an AI agent drive the library needs the mcp extra, so pip install 'sports-betting[mcp]'. Execution needs both extras plus a browser binary, and the README gives the two commands in order: pip install 'sports-betting[mcp,execution]' followed by python -m playwright install chromium. That second command is the tell. The execution path is not an HTTP client against a documented endpoint; for bookmakers without a betting API it drives the website through a browser, which is why Chromium has to be present. Registering the MCP server with an agent is a single command, claude mcp add sportsbet -- sportsbet-mcp. For development the README points at PDM: clone the repository, cd into it, and run pdm install to get main and development dependencies together. The Python example imports DataLoader from sportsbet.dataloaders and FootballDataOdds and FootballDataStats from sportsbet.sources, then constructs the loader with a param_grid keyed on league, division and year. Those four keys are the concrete configuration surface shown in the material.
The agent path is first-class, and it changes the cost model
The README calls the agent a first-class way to use the library and claims it reaches everything Python and the command line reach, plus exploration, tables, plots and model writing. The described session has five steps: ask what data is available, ask for a strategy on leagues and seasons, ask which league holds the edge, ask for value bets in upcoming fixtures, then ask it to place a bet. The cost detail buried in that section matters more than the workflow. Reading the catalogue is free, but extracting the data downloads it, so a paid odds feed spends money only when you extract. The README's own advice is to extract once and save the dataloader instead of extracting again. That is a real operational constraint, not a nicety: an agent that re-extracts on every iteration will bill you on every iteration. On credentials, the README states the agent names the environment variable holding your API key and never prints the key. I cannot verify that behaviour from the material, and prompt-level secrecy guarantees are worth treating with suspicion in general.
Where it is the wrong tool: execution, terms of service and thin documentation
The execution layer is the part to think hardest about. The README describes it as taking a fitted bettor, one match and a stake; it watches the match and places the bet once, at the moment the model was fitted for. Where a bookmaker has a betting API, the library places the bet through it. Where there is no API, your agent drives the website on your own account. The README then states that you place the bet at a bookmaker where you hold an account and that this spends real money, and separately that driving a bookmaker's website on your account breaches most bookmakers' terms of service and risks the account and its balance. That is the project's own documentation telling you the feature can get you banned. Treat execution as a distinct adoption decision from the modelling library. The second limitation is documentation depth. Outside the dataloader and bettor concepts, the material shows one dataloader configuration and one source pair. Everything else, including the full source catalogue, the supported bookmakers, and the behaviour of the single-event execution, is referenced but not specified here. The release cadence is fast, with 0.15.0 and 0.15.1 landing a day apart in July 2026, which is a plausible sign of active work and also a plausible sign that interfaces move.
Alternatives: what a hand-rolled pipeline actually costs you
The realistic alternative is not another betting library. It is a scikit-learn pipeline plus pandas, a scraped or purchased odds feed, and a backtest function you write yourself. The difference in approach is where the abstraction sits. A hand-rolled pipeline gives you total control over the join between results and odds, and you can model the exact market and settlement rules of your bookmaker. It also gives you the maintenance burden: source schemas change, and you own every fix. sports-betting's contribution is the DataLoader boundary, which fixes the contract between a statistics source and an odds source so the join is not rewritten per project. If you only ever use one league and one feed, that abstraction buys you little and the hand-rolled version is simpler. If you want to swap feeds, or run the same model across several leagues and divisions as the param_grid example does, the boundary earns its place. There is no claim in the material that this library produces better predictions than a hand-rolled pipeline, and you should not assume it does.
Licence, maintenance and what a 0.15.x upgrade costs
The repository is MIT licensed, which is permissive and places few obligations on how you use or redistribute the code. That says nothing about your data. Odds feeds carry their own terms, and the README's warning about bookmaker terms of service sits alongside the licence rather than inside it. Nothing here is legal advice; check the terms of each source and each bookmaker yourself. On maintenance, the material shows recent releases in quick succession and a toolchain that includes black, ruff, mypy, docformatter, pytest with coverage, interrogate, safety, bandit, nox, pre-commit and mkdocs, which suggests the project holds itself to a documented standard. What the material does not show is a deprecation policy, a changelog, or a statement about version compatibility. With 0.15.x arriving within days of each other, pinning an exact version in your own dependency file is the concrete defensive step available to you, and re-running your backtest after any bump is the only way to know whether a dataloader change altered your training matrix.
Editorial conclusion
Adopt it if you already work in scikit-learn, you want the choice of statistics and odds source to be explicit in your code, and you are prepared to treat the execution layer as a separate, higher-risk decision. Do not adopt it if your goal is a turnkey tipster service, or if you cannot afford to re-extract data after a paid odds feed has been billed. Before writing any model, verify which sources your chosen dataloader actually supports, confirm the licence terms of the odds feed you intend to use, and read your bookmaker's terms of service before enabling the execution extra.
Community notes