DEV Community

FootInsights
FootInsights

Posted on

An open, append-only dataset of 25,000+ settled football predictions (CSV, CC BY 4.0)

Football prediction sites rarely show their misses. Records get edited, bad months vanish, and "verified" win rates can't be checked by anyone.

We went the other way. Every prediction we publish is written to the database before kick-off, settled automatically at full time, and never edited or deleted afterwards. The whole ledger is a plain CSV that anyone can download.

What's in it

  • 25,816 settled predictions across 2,519 matches in 60+ competitions: Premier League, La Liga, Serie A, Bundesliga, MLS, Liga MX, the Champions League and many more.
  • It starts on 16 Aug 2026 and grows every matchday. Rows are only ever appended.
  • One row per prediction: the market (1X2, double chance, over/under 1.5/2.5/3.5, both teams to score, correct score), the probabilities published before kick-off, the final score, and whether the call was right.
  • Losing runs are in there too. That is the point.

Main columns: kickoff_utc, league, home_team, away_team, home_goals, away_goals, market, predicted, actual, correct, p_home, p_draw, p_away, p_over25, p_btts, settled_at, match_url.

Check us yourself

A Brier score and a quick calibration table for the 1X2 market, in a few lines of pandas:

import numpy as np
import pandas as pd

df = pd.read_csv("https://footinsights.com/data/predictions.csv")
res = df[df["market"] == "1x2"].copy()

# Brier score: 0 is perfect, lower is better
probs = res[["p_home", "p_draw", "p_away"]].to_numpy()
outcome = np.eye(3)[res["actual"].map({"home": 0, "draw": 1, "away": 2})]
print("Brier score:", ((probs - outcome) ** 2).sum(axis=1).mean().round(3))

# Calibration: when we said "60% home win", how often did it happen?
res["bucket"] = (res["p_home"] * 10).astype(int) / 10
print(
    res.groupby("bucket").agg(
        matches=("p_home", "size"),
        predicted=("p_home", "mean"),
        happened=("actual", lambda a: (a == "home").mean()),
    ).round(2)
)
Enter fullscreen mode Exit fullscreen mode

If the predicted and happened columns sit close together, the probabilities mean what they say. If they drift apart, you will see exactly where.

Ideas for the data

  • Compare the published probabilities with bookmaker-implied ones and look for where they disagree.
  • Test calibration league by league, or market by market.
  • Use it as a baseline to beat with your own model.

Where to get it

It is licensed CC BY 4.0, so use it freely and cite it. Questions about the columns or ideas for what else to publish are welcome in the comments.

Top comments (0)