On 2 October 2006 Netflix opened a contest with a plain offer: a million dollars to whoever made its recommendation system, Cinematch, 10% more accurate. The rules added a $50,000 Progress Prize for every year the contest ran, and they said what a winner would owe besides the winning score: “you must share your method with (and non-exclusively license it to) Netflix, and you must describe to the world how you did it and why it works.” They also said why anyone might enter: “So if you know (or want to learn) something about machine learning and recommendation systems, give it a shot.”
A year in, a team called KorBell won the first Progress Prize with an 8.43% improvement. Netflix later wrote that “They reported more than 2000 hours of work in order to come up with the final combination of 107 algorithms that gave them this prize”, and it put two of those algorithms into production. The Grand Prize went on 21 September 2009 to BellKor’s Pragmatic Chaos, whose 10.06% improvement had arrived “just 24 minutes before the conclusion of the nearly three-year-long contest.” By the end the leaderboard counted 51,051 contestants on 41,305 teams from 186 countries.
Netflix did not put the million-dollar solution into production. In 2012 two of its engineers, Xavier Amatriain and Justin Basilico, wrote: “We evaluated some of the new methods offline but the additional accuracy gains that we measured did not seem to justify the engineering effort needed to bring them into a production environment.”
Kaggle, founded in 2010, turned the prize contest into a platform. Its first competition asked for forecasts of the voting in the Eurovision Song Contest, and its chief executive Anthony Goldbloom recalled in 2017 that the winner “beat 21 teams to win the $1000 prize”. In March 2017 Kaggle joined Google Cloud.
Kaggle publishes a record of its competitions as Meta Kaggle, a dataset under the Apache 2.0 licence, updated daily, so that people can study it; in 2025 it ran a $50,000 Featured competition, the Meta Kaggle Hackathon, that asked for exactly that. This notebook is one such study, and it asks the question Netflix’s million raises: what is an entry worth in cash? An entry is a lottery ticket paid for in hours instead of dollars. Here is the ticket’s price, measured from Kaggle’s record: the pot per entry, the chance that a team is paid, and the most the pot can pay for an hour of work. An entry also comes with a course on real data, medals and a public record; the notebook prices only the ticket, and the reader judges the course.
Kaggle’s Record
The data file holds one row per competition, all 12,485 in Meta Kaggle’s `Competitions.csv` as downloaded on 11 October 2026, with or without cash, and the effort measured from its `Teams.csv` and `Submissions.csv` (below). A competition is finished if its deadline is before 11 October 2026 and it has competitors, and it is a cash competition if its reward is in US dollars and above zero.
Kaggle’s Record
import numpy as np
import pandas as pd
df = pd.read_csv("data/kaggle_competitions.csv", parse_dates=["deadline"])
done = (df["deadline"] < "2026-10-11") & (df["competitors"] > 0)
usd = df["reward_type"].eq("USD") & (df["reward_usd"] > 0)
cash = done & usd
other = done & df["reward_type"].isin(["EUR", "GBP"]) # left out
none = done & ~cash & ~other
print(f"{len(df):,} competitions, {done.sum():,} finished: {cash.sum()} "
f"paid cash in dollars,\n{other.sum()} in euros or pounds, and "
f"{none.sum():,} ({none.sum() / done.sum():.1%}) offered no cash")
seg = pd.DataFrame({"finished": done, "cash": cash, "no cash": none})
seg = seg.groupby(df["segment"]).sum()
seg["share with no cash"] = (seg["no cash"] / seg["finished"]).map(
"{:.1%}".format)
print(seg.sort_values("finished", ascending=False).to_string())
gone = ~done & usd & (df["deadline"] < "2026-10-11")
small = cash & (df["reward_usd"] < 100)
print(f"\npast the deadline, cash, no competitors on record: {gone.sum()},"
f" {df.loc[gone, 'reward_usd'].sum():,.0f} dollars")
print(f"cash pots under 100 dollars: {small.sum()}, together "
f"{df.loc[small, 'reward_usd'].sum():,.0f} dollars; at 1 dollar: "
f"{(df.loc[small, 'reward_usd'] == 1).sum()}")
cm = cash & df["segment"].eq("Community")
print(f"Community cash competitions: {cm.sum()}, "
f"{df.loc[cm, 'reward_usd'].sum():,.0f} dollars, "
f"{df.loc[cm, 'competitors'].sum():,} entries")
# 12,485 competitions, 10,222 finished: 649 paid cash in dollars,
# 2 in euros or pounds, and 9,571 (93.6%) offered no cash
# finished cash no cash share with no cash
# segment
# Community 9539 191 9347 98.0%
# Featured 314 309 5 1.6%
# Research 185 142 42 22.7%
# Playground 160 4 156 97.5%
# Recruitment 17 2 15 88.2%
# Getting Started 6 0 6 100.0%
# Analytics 1 1 0 0.0%
#
# past the deadline, cash, no competitors on record: 41, 1,522,375 dollars
# cash pots under 100 dollars: 20, together 201 dollars; at 1 dollar: 11
# Community cash competitions: 191, 1,219,244 dollars, 33,991 entries
Of the 10,222 finished competitions, 9,571, or 93.6%, offered no cash prize: their stated reward is Knowledge, Kudos, Swag, Jobs or Prizes, or none at all. Most of them are Community competitions, which are 9,539 of the 10,222, and 98.0% of those pay no cash. The Featured competitions are the other way round, 309 of 314 with a cash prize, and so are three Research competitions in four. Money was never the main offer of most Kaggle competitions; in the Featured ones it is part of it.
Three more choices, stated so they can be checked. The one competition paid in euros and the one paid in pounds are left out. Forty-one cash competitions whose deadlines have passed list no competitors at all, among them the NFL Big Data Bowls and Kaggle’s annual survey challenges, with $1,522,375 between them; with no entries to divide by, they are left out too. And each pot is taken as stated: twenty Community competitions state pots under $100, eleven of them $1, which reads more like a placeholder than a prize; together they hold $201. A few other Community rows may be tests rather than contests, but all 191 Community cash competitions together hold $1.2 million of the $36.4 million and 33,991 of the 749,385 entries, so no choice about them moves the totals much.
The Ticket’s Cash Value
An entry is one person in one competition, so the same person in ten competitions is ten entries. Take a competition with a pot of $P$ dollars and $E$ entries. However the pot is split, the prizes $x_1, \dots, x_E$ paid to the entries add up to $P$, so the average entry receives
the cash value of an entry drawn at random. A team’s chance of any prize is about $K/T$, with $K$ prize places and $T$ teams. Netflix’s Grand Prize, priced this way, was worth $19.59 to each of its 51,051 contestants.
The Ticket’s Cash Value
c = df[cash].copy()
c["per_entry"] = c["reward_usd"] / c["competitors"]
P, E = c["reward_usd"].sum(), c["competitors"].sum()
T, K = c["teams"].sum(), c["num_prizes"].sum()
print(f"{len(c)} cash competitions, ${P:,.0f} in prizes")
print(f"{E:,} entries in {T:,} teams; {K:,} prize places")
print(f"chance that a team is paid: {K / T:.3%}, 1 in {T / K:.0f}")
print(f"pot per entry: ${P / E:.2f} pooled, "
f"${c['per_entry'].median():.2f} in the median competition")
big = c[c["competitors"] >= 1000]
print(f"{len(big)} competitions with 1,000 entries or more: "
f"${big['reward_usd'].sum() / big['competitors'].sum():.2f} "
f"pooled, ${big['per_entry'].median():.2f} median")
print(f"Netflix Prize: ${1_000_000 / 51_051:.2f} per contestant")
# 649 cash competitions, $36,432,739 in prizes
# 749,385 entries in 628,198 teams; 2,087 prize places
# chance that a team is paid: 0.332%, 1 in 301
# pot per entry: $48.62 pooled, $24.39 in the median competition
# 258 competitions with 1,000 entries or more: $39.24 pooled, $20.57 median
# Netflix Prize: $19.59 per contestant
Across the 649 cash competitions, $36.4 million was divided among 749,385 entries: $48.62 an entry, pooled. The median competition paid $24.39 an entry, and the 258 competitions with 1,000 entries or more paid $39.24 pooled and $20.57 at the median. The 2,087 prize places went to 628,198 teams: a team’s chance of any prize was 0.33%, about 1 in 301.
Five of these competitions were run by trading firms on market data, and the Meta Kaggle Hackathon asked for studies of this very record:
Five Finance Competitions and the Hackathon
FINANCE = ["jane-street-market-prediction", "g-research-crypto-forecasting",
"optiver-trading-at-the-close",
"jane-street-real-time-market-data-forecasting",
"hull-tactical-market-prediction"]
NAMES = dict(zip(FINANCE + ["meta-kaggle-hackathon"], [
"Jane Street 2021", "G-Research Crypto 2022", "Optiver 2024",
"Jane Street 2025", "Hull Tactical 2026", "Meta Kaggle Hackathon 2025"]))
f = c.set_index("slug").loc[list(NAMES)]
print(f"{'':27}{'pot':>9}{'entries':>9}{'prizes':>8}{'per entry':>11}"
f" record")
for s, r in f.iterrows():
print(f"{NAMES[s]:27}{r['reward_usd']:9,.0f}{r['competitors']:9,}"
f"{r['num_prizes']:8}{r['per_entry']:11.2f} {r['record']}")
# pot entries prizes per entry record
# Jane Street 2021 100,000 4,884 9 20.48 truncated
# G-Research Crypto 2022 125,000 2,398 10 52.13 truncated
# Optiver 2024 100,000 4,374 10 22.86 truncated
# Jane Street 2025 120,000 3,643 10 32.94 truncated
# Hull Tactical 2026 100,000 4,096 6 24.41 truncated
# Meta Kaggle Hackathon 2025 50,000 148 1 337.84 none
The five finance competitions sit near the middle, between $20 and $52 an entry. The Meta Kaggle Hackathon paid $50,000 among 148 entrants, $337.84 an entry, fourteen times the median competition; it was judged by a panel on written reports, and its rules list six prizes in two tracks where the data’s prize count says one.
What a sponsor receives is written in each competition’s rules, which Meta Kaggle also carries. Jane Street’s 2025 rules list prizes from $50,000 for first place down to $5,000 for fourth to tenth, a “WINNER LICENSE TYPE: Non-exclusive license”, and, “As a condition to being awarded a Prize”, that the winner “deliver to the Competition Sponsor the final model’s software code as used to generate the winning Submission and associated documentation.” The rules of Optiver’s Trading at the Close carry the same two terms, and the Meta Kaggle Hackathon’s winners license their work under CC BY 4.0. Netflix asked its winners for a non-exclusive licence too, in 2006.
The same division priced a lottery ticket in an earlier notebook, Is a Lottery Ticket Ever Worth Buying?. A Cash WinFall ticket on a roll-down draw was worth $c_0 + J/N$: the fixed prizes, plus the rolled-down jackpot $J$ shared among the $N$ tickets sold, however it was split between the prize tiers. It was worth buying whenever that came to more than the two dollars the ticket cost. A Kaggle entry’s $P/E$ is the same expected value, with no fixed prizes, and its price is paid in hours.
Year by Year
Each competition counts in the year of its deadline; 2026 runs to 10 October.
Year by Year
c["year"] = c["deadline"].dt.year
yr = c.groupby("year").agg(n=("slug", "size"), pot=("reward_usd", "sum"),
entries=("competitors", "sum"),
median=("per_entry", "median"))
yr["pooled"] = yr["pot"] / yr["entries"]
top = c.sort_values(["reward_usd", "slug"], kind="stable")
top = top.groupby("year").tail(2) # each year's two largest pots
rest = c.drop(top.index).groupby("year")[["reward_usd", "competitors"]].sum()
yr["without top 2"] = rest["reward_usd"] / rest["competitors"]
print(f"{'year':>4}{'comps':>7}{'pot':>12}{'entries':>9}{'pooled':>8}"
f"{'median':>8}{'without its 2 largest pots':>28}")
for y, r in yr.iterrows():
print(f"{y:>4}{r['n']:7.0f}{r['pot']:12,.0f}{r['entries']:9,.0f}"
f"{r['pooled']:8.2f}{r['median']:8.2f}{r['without top 2']:28.2f}")
for y in (2017, 2025):
print(f"\n{y}, the largest pots:")
for _, r in c[c["year"] == y].nlargest(6, "reward_usd").iterrows():
print(f" {r['title'][:44]:45}{r['reward_usd']:10,.0f}"
f"{r['competitors']:6,}{r['per_entry']:7,.0f} an entry")
# year comps pot entries pooled median without its 2 largest pots
# 2010 6 3,217 573 5.61 6.32 5.59
# 2011 15 72,050 3,279 21.97 24.15 18.07
# 2012 32 557,130 7,038 79.16 57.10 53.63
# 2013 33 1,173,150 12,341 95.06 16.13 40.19
# 2014 23 725,180 13,924 52.08 24.81 20.75
# 2015 26 778,500 32,248 24.14 20.98 17.68
# 2016 22 1,060,000 36,639 28.93 21.06 21.52
# 2017 25 3,500,000 36,178 96.74 43.16 28.39
# 2018 31 2,272,500 58,296 38.98 18.94 19.32
# 2019 36 1,170,000 74,814 15.64 15.11 13.36
# 2020 28 1,951,000 61,854 31.54 19.45 14.50
# 2021 26 1,160,500 51,635 22.48 17.90 21.14
# 2022 32 1,678,000 62,875 26.69 24.66 23.72
# 2023 36 3,158,000 63,307 49.88 40.39 32.49
# 2024 39 3,941,422 67,168 58.68 26.32 27.96
# 2025 107 8,285,903 74,435 111.32 17.86 69.40
# 2026 132 4,946,187 92,781 53.31 26.03 28.52
#
# 2017, the largest pots:
# Passenger Screening Algorithm Challenge 1,500,000 217 6,912 an entry
# Data Science Bowl 2017 1,000,000 742 1,348 an entry
# The Nature Conservancy Fisheries Monitoring 150,000 554 271 an entry
# Two Sigma Financial Modeling Challenge 100,000 2,317 43 an entry
# Dstl Satellite Imagery Feature Detection 100,000 519 193 an entry
# Google Cloud & YouTube-8M Video Understandin 100,000 821 122 an entry
#
# 2025, the largest pots:
# AI Mathematical Olympiad - Progress Prize 2 2,117,152 2,672 792 an entry
# Konwinski Prize 1,225,000 531 2,307 an entry
# ARC Prize 2025 1,000,000 1,684 594 an entry
# OpenAI to Z Challenge 500,000 309 1,618 an entry
# Red‑Teaming Challenge - OpenAI gpt-oss-20b 500,000 778 643 an entry
# Google DeepMind - Vibe Code with Gemini 3 Pr 500,000 4,862 103 an entry
From 2015 to 2026 the pooled pot per entry ranged from $15.64 (2019) to $111.32 (2025), while the median competition stayed between $15.11 and $43.16. The years that stand out are lifted by a few very large pots. In 2017 the Passenger Screening Algorithm Challenge put $1.5 million before 217 entries, $6,912 each, and the Data Science Bowl 2017 $1 million before 742; without those two, the year’s $96.74 falls to $28.39. In 2025 the AI Mathematical Olympiad’s Progress Prize 2 ($2.1 million) and the Konwinski Prize ($1.2 million among 531 entries) lift it from $69.40 to $111.32, and below them sit the ARC Prize 2025’s $1 million and three pots of $500,000. Figure 1 draws the years.

Across the Competitions
The pooled numbers weigh each competition by its entries. One competition at a time, the pot per entry spreads over six orders of magnitude, from under a cent, where a $1 pot met 139 entrants, to $30,000 in the AI Mathematical Olympiad’s Proof Pilot, where seven competitors entered for $210,000. A quarter of the competitions paid under $9.89 an entry, a quarter over $51.92, and Figure 2 shows where the finance competitions and the Hackathon fall.
Across the Competitions
q = c["per_entry"].quantile([0.1, 0.25, 0.5, 0.75, 0.9])
print("pot per entry in the 649 competitions, dollars, by percentile:")
print(" ".join(f"{k:.0%}: {v:,.2f}" for k, v in q.items()))
print(f"under 1 dollar: {(c['per_entry'] < 1).sum()}, "
f"over 1,000: {(c['per_entry'] > 1000).sum()}")
lo, hi = c.loc[c["per_entry"].idxmin()], c.loc[c["per_entry"].idxmax()]
print(f"lowest: {lo['per_entry']:.4f} an entry, {lo['reward_usd']:,.0f} "
f"dollar among {lo['competitors']} ({lo['segment']})")
print(f"highest: {hi['per_entry']:,.0f} an entry, {hi['reward_usd']:,.0f} "
f"dollars among {hi['competitors']},\n {hi['title']}")
# pot per entry in the 649 competitions, dollars, by percentile:
# 10%: 3.75 25%: 9.89 50%: 24.39 75%: 51.92 90%: 144.03
# under 1 dollar: 27, over 1,000: 13
# lowest: 0.0072 an entry, 1 dollar among 139 (Community)
# highest: 30,000 an entry, 210,000 dollars among 7,
# AI Mathematical Olympiad - Proof Pilot

Days of Work
Kaggle’s record has no hours in it, but it dates every submission. For each entry, one submitting person in one competition (a submission with no person on it counts for its team), the derivation behind the data file counted the distinct days with a submission before the deadline, the entry’s active days, and the span from its first submission to its last, and wrote only per-competition totals and counts, with no person in them.
Meta Kaggle says of itself that it “is not a complete dump of our database. Rows, columns, and tables have been filtered out and transformed”, and for this question the record has two gaps, both measured. In 38 competitions with $8,757,980 in prizes, the record shows a single active day for nearly every entry (1.05 days an entry or fewer): 32 of them are code competitions, all five finance ones among them, and their records keep one submission row per entry, so the effort is cut off. Another 200 cash competitions, with $3,672,744, have no submission rows at all. Both groups are left out of the measured rate, which rests on the 411 competitions whose records are complete.
Every gap flatters the prize. Days of work without a submission are not counted, and neither are teammates who never pressed submit: the 411 competitions list 632,065 competitors and 607,092 submitting entries. So the measured days are a lower bound on the work, and every hourly rate below is a ceiling.
Days of Work
rec = c.groupby("record").agg(competitions=("slug", "size"),
prize_dollars=("reward_usd", "sum"),
code_competitions=("code_competition", "sum"))
print(rec.to_string(formatters={"prize_dollars": "{:,.0f}".format}))
# competitions prize_dollars code_competitions
# record
# complete 411 24,002,015 120
# none 200 3,672,744 1
# truncated 38 8,757,980 32
Active Days per Entry
m = c[c["record"] == "complete"]
D, n_e = int(m["active_days"].sum()), int(m["submitting_entries"].sum())
print(f"{len(m)} competitions with complete records, "
f"${m['reward_usd'].sum():,.0f}:\n{n_e:,} submitting entries of "
f"{m['competitors'].sum():,} competitors, {D:,} active entry-days")
BINS = ["1", "2", "3", "4", "5 to 9", "10 to 29", "30 or more"]
k = ["1d", "2d", "3d", "4d", "5to9d", "10to29d", "30d_plus"]
entries = np.array([m[f"entries_{x}"].sum() for x in k], dtype=int)
days = np.array([(i + 1) * entries[i] for i in range(4)]
+ [m[f"days_{x}"].sum() for x in k[4:]], dtype=int)
assert entries.sum() == n_e and days.sum() == D
mid = BINS[np.searchsorted(entries.cumsum(), n_e / 2)]
print(f"active days per entry: median {mid}, mean {D / n_e:.2f}")
# 411 competitions with complete records, $24,002,015:
# 607,092 submitting entries of 632,065 competitors, 3,941,704 active entry-days
# active days per entry: median 3, mean 6.49
Where the Days Go
print(f"{'active days':>12}{'entries':>10}{'share':>8}{'their days':>12}"
f"{'share':>8}")
for b, e, d in zip(BINS, entries, days):
print(f"{b:>12}{e:10,}{e / n_e:8.1%}{d:12,}{d / D:8.1%}")
for i, lo in ((5, 10), (6, 30)):
print(f"{lo} days or more: {entries[i:].sum() / n_e:.1%} of entries, "
f"{days[i:].sum() / D:.1%} of the days")
Dp = int(m["prize_active_days"].sum())
n_p = int(m["prize_entries"].sum())
print(f"prize-winning entries: {n_p:,}, {Dp / n_p:.1f} active days each, "
f"{Dp / D:.1%} of all the days")
# active days entries share their days share
# 1 183,641 30.2% 183,641 4.7%
# 2 95,702 15.8% 191,404 4.9%
# 3 57,199 9.4% 171,597 4.4%
# 4 41,597 6.9% 166,388 4.2%
# 5 to 9 110,371 18.2% 728,926 18.5%
# 10 to 29 97,186 16.0% 1,572,073 39.9%
# 30 or more 21,396 3.5% 927,675 23.5%
# 10 days or more: 19.5% of entries, 63.4% of the days
# 30 days or more: 3.5% of entries, 23.5% of the days
# prize-winning entries: 2,900, 21.9 active days each, 1.6% of all the days
In the 411 competitions with complete records, 607,092 entries submitted on 3,941,704 entry-days: the median entry was active on 3 days and the mean on 6.49. Most of the work is done by a few. The 19.5% of entries active on ten days or more put in 63.4% of all the active days, and the 3.5% active on thirty or more put in 23.5%. The 2,900 prize-winning entries averaged 21.9 active days each, and together they put in 1.6% of the days. Figure 3 shows the split.

The Price of an Hour
With $D$ measured active entry-days and $h$ hours of work behind each, the pot pays
dollars an hour. It is a ceiling twice over. $D$ is a lower bound on the days, and $r$ is the rate only if every hour were paid the same, which no contest does: the mean payout per entry is $P/E$, but the median is zero whenever fewer than half the entries are paid, and here 0.48% of the submitting entries were.
One assumption is left, the hours of work behind an active day. We bracket it at 2 to 4 hours, with 3 in the middle; the bracket is ours. The published accounts we could read point higher, and more hours would only lower every rate here. A Kaggle gold medallist “spent about four to five hours a day preparing for the competition”, in his employer’s news story of 2023. A survey of the participants of 80 biomedical imaging challenges, held with two conferences in 2021, found that “a median of 80 working hours was spent on method development”, where the median entry here was active on 3 days. And Netflix’s first Progress Prize winners reported more than 2,000 hours for their $50,000.
The Price of an Hour
Pm = m["reward_usd"].sum()
print(f"${Pm / D:.2f} per active entry-day; "
f"${Pm / m['span_days'].sum():.2f} per day of span")
for h in (2, 3, 4):
print(f" at {h} hours an active day: ${Pm / (D * h):.2f} an hour")
print(f"prize-winning entries: ${Pm / Dp:.0f} per active day, "
f"${Pm / (Dp * 8):.0f} an hour at 8 hours a day")
print(f"share of submitting entries paid: {n_p / n_e:.2%}")
# $6.09 per active entry-day; $2.12 per day of span
# at 2 hours an active day: $3.04 an hour
# at 3 hours an active day: $2.03 an hour
# at 4 hours an active day: $1.52 an hour
# prize-winning entries: $378 per active day, $47 an hour at 8 hours a day
# share of submitting entries paid: 0.48%
The 411 competitions paid $24.0 million for 3.94 million recorded active entry-days: at most $6.09 an active day. At 2, 3 and 4 hours a day that is $3.04, $2.03 and $1.52 an hour. Counted by calendar days, from each entry’s first submission to its last, it is $2.12 a day. For the prize-winning entries alone, the same pot comes to $378 an active day, and even at 8 hours a day, $47 an hour.
Your Own Hours
Set the knob to the hours you would put behind each day on which you submit. The cell prints the ceiling for the 411 competitions and for their prize winners, the table for other hours, and an estimate for the five finance competitions, whose truncated records cannot measure their days: each of their entrants is given the average effort measured where the record is complete, 6.49 active days, so their rates are estimates, not measurements. For scale only, since an entry is not a job, the US federal minimum wage is $7.25 an hour.
Your Own Hours
HOURS_PER_ACTIVE_DAY = 3 # hours of work behind each day with a submission
h = HOURS_PER_ACTIVE_DAY
per = D / n_e # 6.49 active days per entry, complete records
print(f"at {h} hours per active day, the most the pot pays is "
f"${Pm / (D * h):.2f} an hour;\nfor the prize-winning entries, "
f"${Pm / (Dp * h):.2f} an hour")
print(f"\n{'hours a day':>12}{'all entries':>13}{'prize winners':>15}")
for x in (1, 2, 3, 4, 6, 8):
print(f"{x:>12}{Pm / (D * x):13.2f}{Pm / (Dp * x):15.2f}")
print(f"\nfinance competitions, estimated at {per:.2f} active days "
f"an entry, {h} hours a day:")
for s, r in f.loc[FINANCE].iterrows():
rate = r["reward_usd"] / (r["competitors"] * per * h)
print(f" {NAMES[s]:24}${rate:.2f} an hour (estimate)")
# at 3 hours per active day, the most the pot pays is $2.03 an hour;
# for the prize-winning entries, $126.01 an hour
#
# hours a day all entries prize winners
# 1 6.09 378.04
# 2 3.04 189.02
# 3 2.03 126.01
# 4 1.52 94.51
# 6 1.01 63.01
# 8 0.76 47.25
#
# finance competitions, estimated at 6.49 active days an entry, 3 hours a day:
# Jane Street 2021 $1.05 an hour (estimate)
# G-Research Crypto 2022 $2.68 an hour (estimate)
# Optiver 2024 $1.17 an hour (estimate)
# Jane Street 2025 $1.69 an hour (estimate)
# Hull Tactical 2026 $1.25 an hour (estimate)

What the Numbers Show
Most Kaggle competitions pay no cash: 93.6% of the finished ones offered none, and money was never their main offer. Where there is cash, an entry’s share of the pot is $48.62 pooled and $24.39 in the median competition (Netflix’s million came to $19.59 for each of its contestants), and a team’s chance of any prize is about 1 in 301. Measured against the days on which people submitted, the 411 competitions with complete records paid at most $6.09 for an active day: $2.03 an hour at three hours a day, as a ceiling, because the days without a submission are not in the record. For the 0.48% of submitting entries that won a prize, the same ceiling is $126 an hour.
A contest that pays a few, and little on average, is working as a tournament is designed to. Edward Lazear and Sherwin Rosen’s study of rank-order pay, published in 1981, starts from schemes that pay “according to an individual’s ordinal rank in an organization rather than his output level”, and shows that with risk-neutral workers they “induce the same efficient allocation of resources as an incentive reward scheme based on individual output levels”. The small average is a property of the contest: a pot divided among many entries.
And cash is not why most people enter. In the survey of biomedical imaging challenges, “knowledge exchange was the primary incentive (70%) for participation, while the reception of prize money played only a minor role (16%)”. Netflix’s rules made the same invitation in 2006, to those who wanted to learn, and Goldbloom wrote in 2017 that “Kaggle profiles have become a well recognized credential”. An entry is a lottery ticket bundled with a course on real data, a public record of the work, medals and a sport. This notebook has priced the ticket; the reader judges the course.
Sources
- Netflix Prize, Rules, netflixprize.com (Internet Archive copy, 2009): the start date, the $1,000,000 Grand Prize, the $50,000 Progress Prize, the winners’ licence, the invitation to enter.
- Netflix Prize, home page, leaderboard and forum announcement “Grand Prize awarded to team BellKor’s Pragmatic Chaos”, 18 September 2009, netflixprize.com (Internet Archive copies, 2009–2010).
- X. Amatriain and J. Basilico, “Netflix Recommendations: Beyond the 5 stars (Part 1)”, The Netflix Tech Blog, 6 April 2012.
- F.-F. Li, “Welcome Kaggle to Google Cloud”, Google Cloud Blog, 8 March 2017.
- A. Goldbloom, “Kaggle Joins Google Cloud”, No Free Hunch, Kaggle’s blog, 8 March 2017 (Internet Archive copy).
- Kaggle, Meta Kaggle (kaggle/meta-kaggle), Apache 2.0: `Competitions.csv`, `Teams.csv` and `Submissions.csv`, downloaded 11 October 2026; the data file of this notebook is derived from them, with credit.
- E. P. Lazear and S. Rosen, “Rank-Order Tournaments as Optimum Labor Contracts”, Journal of Political Economy 89 (1981) 841–864, doi:10.1086/261010; quoted from the abstract of its working paper, NBER Working Paper 401 (1979).
- M. Eisenmann et al., “Biomedical image analysis competitions: The state of current participation practice”, arXiv:2212.08568 (2022, revised 2023).
- SoftBank News, “SoftBank Corp. Data Scientist Wins Gold Medal at World’s Largest AI Competition”, 13 September 2023.
- US Department of Labor, Wage and Hour Division, “Minimum Wage”: “The federal minimum wage is $7.25 per hour effective July 24, 2009″, read 11 October 2026.
Every number in this notebook that is not quoted from a source is computed by its own cells from the data file.
Interested in applying these ideas to your work? Get in touch.