116,917 tennis matches before 2015, results and odds.
The history before 2015, with the same 39 columns as our 2015-2026 archive: the two editions stack into one series from 2004 to 2026. By season, as a 2004-2014 bundle or as the complete history.
Choose your option
Same columns for every season. The price covers the file as it is at purchase time, unless marked “updated”.
One season
One season, one file, with the full README. 2004 and 2005 only cover the ATP main tour (book b only): read the coverage below before buying a single season.
Download link valid 72 h, 5 downloads
Buy season 2014Bundle 2004 → 2014
Jan 5, 2004 → Nov 23, 2014, all eleven seasons.
- 116,917 matches, one file per season + one combined file
- Same columns and ids as the 2015-2026 archive
- CSV + Parquet
Download link valid 72 h, 5 downloads
Buy — €192004 → 2026
The whole history in one download: the 2004-2014 bundle plus the 2015-2026 archive (2026 season frozen on 5 September 2026).
- 684,828 matches, Jan 5, 2004 → Sep 5, 2026
Download link valid 72 h, 5 downloads
Buy — €39Did favourites win as often as the odds said?
2004-2014 singles, grouped by the favourite's probability (margin-free consensus), against the actual result.
Descriptive chart, for illustration only: it is not a strategy.
| FAVOURITE PROB. | MATCHES | Favourite wins | Upset | Implied |
|---|---|---|---|---|
| 50-60 % | 34,743 | 55.7% | 44.3% | 55.2% |
| 60-70 % | 34,606 | 66.3% | 33.7% | 64.8% |
| 70-80 % | 22,725 | 77.3% | 22.7% | 74.5% |
| 80-90 % | 11,418 | 87.0% | 13.0% | 84.3% |
| ≥ 90 % | 3,244 | 95.8% | 4.2% | 92.8% |
Built for long-horizon modelling
p1 is always the player with the lower id, never the winner: no result leakage in the file layout.
Stack the editions
Same columns and ids: one series from 2004 to 2026.
h = pd.read_parquet("tennis_results_odds_2004_2014.parquet")
r = pd.read_parquet("tennis_results_odds_2015_2026.parquet")
t = pd.concat([h, r])Calibrate a model
Margin-free consensus probability against the actual result.
s = h[h.is_doubles == 0]
s.groupby(pd.cut(s.consensus_prob_p1, 10)).result
.apply(lambda r: (r == "P1").mean())By surface
Clay, hard, grass, carpet: compare how favourites fare.
s.groupby("surface").result.value_counts(normalize=True)Thinner before 2010, and we say so.
2004 and 2005 only cover ATP main-tour events, priced by book b alone; WTA, Challengers and book a arrive in 2006, doubles in 2010. Of the singles matches in our database, the share with odds (and therefore in these files) is 90-100% for Grand Slams from 2006, 68-78% for ATP/WTA tour events in 2006-2012, then 85% in 2013 and 97% in 2014.
Checked before release, season by season: reference matches (Wimbledon 2008 final, Federer favourite at 1.75), pre-match prices (on completed matches, sides at 1.03 or shorter still lose 2.7% of the time at book a, 2.1% at book b), calibration of the consensus, orientation of totals and handicaps against final scores. Details are in the README.
Two bookmakers labelled a and b, as in the 2015-2026 archive: the source does not document their identity. b has the lower margin (2.5% on average before 2015). Before 2015, totals and handicaps are essentially book a's, always in games.
What's in the file — and what isn't
Included
- Result, score, retirements and walkovers
- Tournament, level, surface, round, format
- Pre-match odds from two bookmakers
- Best price and consensus probability (ProbWin)
Not included
- Closing line and timestamps
- ITF entry level (from 2016, in the 2015-2026 archive)
- WTA, Challengers and book a in 2004-2005
Every column, with its fill rate
Measured on the delivered file. 100% = no missing values.
Match
Identity, tour, date, tournament, level, surface, round, format
Players
Ids and names (p1 = lower id), doubles
Result
Winner P1/P2, score, retirement, walkover
Odds
Odds of bookmakers a and b, best price, consensus probability
Totals & handicaps
Total and handicap when offered, in games (b_total_unit, b_handicap_unit)
The file, exactly as you'll get it
Six real rows, main columns. Download 50 free rows with every column to check it fits your pipeline.
| match_date | tour | tournament_name | surface | round_name | p1_name | p2_name | result | score | a_odds_p1 | a_odds_p2 | best_odds_p1 | best_odds_p2 | consensus_prob_p1 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2008-01-11 | atp | Medibank International - Sydney | hard | SF | Fabrice Santoro | Dmitry Tursunov | P2 | 6-3 7-6(4) | 2.4 | 1.55 | 2.7 | 1.556 | 0.379 |
| 2008-03-02 | atp | Regions Morgan Keegan Championships - Memphis | indoor_hard | Final | Robin Soderling | Steve Darcis | P2 | 6-3 7-6(5) | 1.2 | 4.2 | 1.2 | 5.5 | 0.7993 |
| 2008-04-23 | atp | Masters Series Monte-Carlo - Monte-Carlo | clay | Second | Olivier Rochus | David Nalbandian | P2 | 6-4 6-3 | 4.6 | 1.18 | 4.8 | 1.238 | 0.2046 |
| 2008-05-13 | atp | Masters Series Hamburg - Hamburg | clay | First | Tommy Robredo | Philipp Kohlschreiber | P1 | 2-6 7-6(5) 6-3 | 1.55 | 2.3 | 1.55 | 2.78 | 0.6217 |
| 2008-06-17 | atp | Nord LB Open - Braunschweig | clay | First | Pablo Andujar | Maximo Gonzalez | P1 | 6-3 6-1 | 1.65 | 2.15 | 1.65 | 2.15 | 0.5658 |
| 2008-10-21 | atp | Grand Prix de Tennis de Lyon - Lyon | carpet | First | Andreas Seppi | David Guez | P1 | 6-2 7-5 | 1.38 | 2.9 | 1.457 | 2.99 | 0.675 |
Before you buy
Can I buy a single season?
Yes: each season from 2004 to 2014 is sold on its own, with the full README. The eleven-season bundle is cheaper from five seasons.
Do the files combine with the 2015-2026 archive?
Yes: same 39 columns, same definitions, same player and match ids. The complete 2004 → 2026 edition already brings them together in one download.
What do 2004 and 2005 contain?
Only ATP main-tour matches (Grand Slams, Masters, other ATP events), about a third of them, priced by book b alone.
What does the tournament_level column mean?
A level code: 0 = ITF entry level (Futures until 2018, M15/W15 since 2019, plus men's M25), 1 = Challengers, WTA 125 and women's ITF W25 to W100, 2 = ATP/WTA 250 and 500 events, 3 = Masters 1000 / WTA 1000, 4 = Grand Slams (qualifying included), 5 = team events (Davis Cup, Billie Jean King Cup), 6 = other (juniors, exhibitions, wildcard play-offs).
Which way is the score written?
Always winner-first, not from p1's side. The result column (P1/P2) gives the winner: to read the score from p1's side, reverse each set when result = P2.
How are walkovers and retirements handled?
The file gives the official winner, including on a walkover (walkover column) or a retirement (retirement column). Bookmakers usually void bets on a walkover and their rules on retirements vary: filter both columns before computing a return.
How do I get the file?
Right after payment a download link appears on screen and is emailed to you. The archive contains CSV and Parquet files plus a README documenting every column.
Can I use it in a commercial product?
Yes for your models, analyses and tools, commercial ones included. Reselling or redistributing the files themselves is not allowed.
A question before buying?
Email [email protected] — the founder answers, usually the same day.