Open data
Liga Portugal open data
The forecasts on the Liga Portugal pages come from static JSON files served from this site, with no key to request and no rate limit. The Beat the Model game keeps each player's picks in their own browser, with no account and no server; the model's data is all here.
If you build something with them, you may use the model's outputs under the CC BY-NC 4.0 licence: non-commercial use, with attribution to estimador.pt and a link back to the source page. The third-party data some files carry are outside that licence (see below). And if you publish, tell us: we like seeing it.
Published files
The list below is generated from what is actually on the server at the moment this page was built.
Season 2026-27
current seasonhttps://estimador.pt/data/football/liga-2026-27/
| File | What it is | Size |
|---|---|---|
| ask.json | For conditional questions about the season (“what if Porto lose at Braga?”): each team's probabilities (title, top three, Europe, relegation) and the open fixtures covered. No page of its own on the site yet. | 37 KB |
| ask_samples.json | A compact sample of the simulated seasons, for answering those questions: in each, the result of every open fixture and every team's final position (the encoding is described in the file itself). | 568 KB |
| contested_ratings.json | Contested possession: probability of winning aerial and ground duels, defenders and midfielders, pooled over the seasons the file itself lists (seasons; four in this version, 2023-24 to 2026-27). Cells that failed a pre-registered gate carry ranking: null.Not under the licence: the duel counts (duels, won, rate_raw), from SofaScore. | 85 KB |
| contrib_ratings.json | Attacking contribution: goals plus assists per 90 above replacement, with interval and the metric's distribution by position. rank_goals_only and rank_change_vs_goals_only count places among every player in the model, not in the published finishing list; /jogadores compares against that list.Not under the licence: each player's minutes, goals and assists (SofaScore). | 28 KB |
| def_ratings.json | Defenders: adjusted plus-minus on goals conceded. May carry diagnostics only, if the model finds the players are not separable from their team-mates.Not under the licence: the action counts in descriptive_actions (SofaScore). | 44 KB |
| game_fixtures.json | The season calendar for the Beat the Model game: every fixture with its kickoff (UTC; kickoff_confirmed says whether it is official yet), its lock time (locks_at), the model's probabilities and when they were published (published_at; probs_source names the file they came from) and the result. In the game, a round closes as a whole at the earliest locks_at of its games. The notes below say where these rules part from the calendar.Not under the licence: the results (home_goals, away_goals), from SofaScore. | 130 KB |
| gk_channels.json | The three goalkeeper axes, published separately and never combined: cross intervention (separable), sweeping (a style), and shot-stopping (a properly-powered null). The seasons used are in the seasons field (four in this version, 2023-24 to 2026-27).Not under the licence: each keeper's counts (y, n), from SofaScore. | 22 KB |
| gk_ratings.json | Goalkeepers: goals prevented against the xGOT of the shots faced, raw and modelled, per 90 minutes and with an interval. Also carries the out-of-sample validation and the shot-exclusion rules.Not under the licence: the shots faced, their xGOT and the goals conceded (SofaScore). | 23 KB |
| injuries.json | Injuries and suspensions by club, with reason, expected return where known, and market value. A dated snapshot.Not under the licence: the whole file: injuries, suspensions and market values from Transfermarkt. | 6 KB |
| market_scorecard.json | An evaluation of the model against the market's closing line, with the number of matches and seasons, the paired standard error on every block, the bookmakers whose prices were used (market_sources), the final-points interval check (calibration) and, in the model field, the model evaluated (which may not be the one publishing the forecasts).Not under the licence: the market's probabilities and errors (the market_* fields), derived from Pinnacle and Bet365 closing odds via football-data.co.uk. | 10 KB |
| mdNN.json 9 files (md00.json … md08.json) | The forecast published after a matchday: simulated standings with title, top-three and relegation (17th or 18th place) probabilities, attack and defence strengths, xPts, and the real table at that moment.Not under the licence: the results (actual_standings, matchday_results), from SofaScore, and the xG in xpts_table (xgf, xga, and the xPts computed from it), from FotMob. | 164 KB |
| mdNN_scenarios.json 8 files (md01_scenarios.json … md08_scenarios.json) | Conditional analysis for the same matchday: decisive fixtures, paths to the title and to survival, and probabilities conditioned on each result. These files are large. | 3.3 MB |
| players.json | The finishing list: goals per 90 minutes above replacement level (SAR), with a 90% credible interval and the change from last season. generated_from.seasons names the seasons used.Not under the licence: each player's minutes, matches and goals (SofaScore). | 19 KB |
| players_detail.json | The per-player detail behind the player pages: season-by-season history and recent matches. appearances_through is the date of the last match included. The pages show only the players in players.json's list, with that list's position and numbers; team is the current squad.Not under the licence: the minutes, matches, goals and assists by season and by match, and each match's rating, from SofaScore. | 148 KB |
| samples.json | Complete seasons drawn from the Monte Carlo simulation — position, points and goal difference for every team in each drawn season, plus points quantiles. | 74 KB |
Season 2025-26
archived seasonhttps://estimador.pt/data/football/liga-2025-26/
| File | What it is | Size |
|---|---|---|
| mdNN.json 19 files (md04.json … md31.json) | The forecast published after a matchday: simulated standings with title, top-three and relegation (17th or 18th place) probabilities, attack and defence strengths, xPts, and the real table at that moment.Not under the licence: the results (actual_standings, matchday_results), from SofaScore, and the xG in xpts_table (xgf, xga, and the xPts computed from it), from FotMob. | 273 KB |
| mdNN_scenarios.json 9 files (md23_scenarios.json … md31_scenarios.json) | Conditional analysis for the same matchday: decisive fixtures, paths to the title and to survival, and probabilities conditioned on each result. These files are large. | 1.5 MB |
| review.json | The review of a finished season: final table, per-team xPts, the gap between points and xPts (luck; not a clean split between luck and skill) and how the title and relegation probabilities moved through the year. In 2025-26, the matchday 4 to 22 forecasts were reconstructed afterwards, on 4 March 2026; each mdNN.json's timestamp shows it.Not under the licence: the final table (SofaScore) and the xG behind the xPts (FotMob). | 24 KB |
The main fields
The matchday files (mdNN.json) are the starting point for almost everything. These are the fields that matter.
| Field | What it is |
|---|---|
| table[] | One entry per team: mean_pts, std_pts, mean_gd and the probabilities p_champion, p_top3 and p_relegation (relegation = finishing 17th or 18th; 16th, which goes to the play-off, does not count). p_champion and p_relegation also carry _lo/_hi: the 3rd and 97th percentiles of the same probability computed over 100 blocks of 500 simulations. That is the spread of a 500-simulation estimate, about ten times the Monte Carlo error of the published number (±0.4 percentage points with 50,000 simulations), and it is not the model's uncertainty. The site does not show them. p_top3 has no _lo/_hi. |
| actual_standings[] | The real table at forecast time: played, points, gf, ga, gd. |
| xpts_table[] | Expected points from each match's xG: xpts, xgf, xga, played. It does not use the model's parameters — an independent read. |
| team_strengths{} | Attack and defence per team, on a log scale centred at zero. Positive defence values mean a worse defence. |
| position_probs{} | Per team, the probability of finishing in each position, first to last. Sums to 1. |
| next_matchday{} | The next matchday with p_home, p_draw and p_away for each fixture. It can include postponed games from earlier matchdays. It does not always carry the whole round: md03, md04 and md05 carry 6, 7 and 8 of the 9 games. |
| matchday_results[] / matches_remaining[] | matchday_results: the results that came in since the previous publication, which can span more than one matchday (postponed or brought-forward games). matches_remaining: games of the current matchday still to play when the file was generated (with kickoff where known); empty once the matchday is over, even with postponed games outstanding. An mdNN.json is not cut exactly at matchday NN: actual_standings says how many games each team had played. |
| season, matchday, model, n_sims, timestamp | Metadata: which season, which matchday, which model, how many simulations, and when it was last generated (UTC, ISO 8601). An mdNN.json is regenerated at the same address while its matchday is played, as results come in, so timestamp is the last regeneration, not the first publication. In 2026-27, model is joint_sot (the previous model) for the pre-season file (md00) and bivcross (the current model, bivariate Poisson with shots on target) from matchday 1 on; all of 2025-26 is joint_sot. The next_matchday of md01, md03, md04 and md08 differs from the game's record (game_fixtures.json) by up to 0.4 pp; in the others it matches. The game's record is the one that counts. |
Notes on the Beat the Model game
Read from game_fixtures.json itself: where the lock and scoring rules part from the calendar.
- Matchday 1: the model's probabilities were published on 10 August 2026, after 8 of its 9 games had started. Nobody could play that round. From matchday 2 on, the probabilities are published before the first game.
- Sp. Braga – Gil Vicente (matchday 2) was postponed to Monday 19 October at 20:15, but it closed with matchday 2, on 14 August 2026 (its original kickoff was 16 August 2026): it is scored on the probabilities the model published for that round.
- The probabilities for matchdays 3, 5, 6, 7 and 9 were frozen before the previous round ended (for example, matchday 9's on 11 October 2026, with matchday 8 still being played until 12 October 2026): they do not include the results still to come. The model is scored in the game on those probabilities, as frozen.
- Each game's record is game_fixtures.json: published_at says when the probabilities were frozen and probs_source which publication they came from (file and commit). The mdNN.json of that name may have been regenerated since, so its timestamp and numbers may not match the game's. Matchdays 1 and 2 have no probs_source.
How to use it
There is no index: matchday files follow the mdNN.json pattern with two digits, and the most recent is the highest number. The current matchday is always the highest NN in the current season's directory.
# one matchday file (the latest is the highest NN)
curl -s https://estimador.pt/data/football/liga-2026-27/md01.json | jq '.table[0]'
# the 2025-26 final table and the points − xPts gap
curl -s https://estimador.pt/data/football/liga-2025-26/review.json | jq '.luck[:3]'Licence and attribution
The estimador.pt model's outputs (probabilities, simulations, scenarios, player ratings and the model evaluation) are under the Creative Commons Attribution 4.0 International licence (CC BY-NC 4.0): you may use, redistribute and transform them, commercial use included, as long as you credit the source (“estimador.pt”, with a link to the corresponding page).
The licence does not cover the third-party data some files carry, marked “Not under the licence” in the list above: results and match statistics (SofaScore), xG (FotMob), bookmaker odds (Pinnacle and Bet365, via football-data.co.uk), and injuries and market values (Transfermarkt). Those data come from their original sources and are not ours to redistribute: to reuse them, follow each source's terms.
The data is provided as is, with no warranty — these are probabilistic forecasts from a statistical model, and by definition they will be wrong some of the time.
Provenance
Results and match statistics (shots on target included) from SofaScore; xG from FotMob; closing odds (Pinnacle and Bet365) via football-data.co.uk; injuries and market values from Transfermarkt. The probabilities come from a bivariate Poisson Bayesian model (bivcross), fitted to goals and shots on target from the last four seasons of the Primeira Liga and Liga 2, with older games counting for less and each squad's value as the starting point, and from 50,000 Monte Carlo season simulations per publication. The pre-season file (md00) was published by the previous model, joint_sot.