Racing the clock
Hi there! This is Elana, co-CEO and lead of the team developing the visualization features at Datawrapper. Today, I'm looking at marathon finishing times — from the fastest runners in the world to the tens of thousands of people behind them.
This April, Sabastian Sawe ran the London Marathon in 1:59:30, the first official marathon under two hours. Not only that, but he was one of two who managed it in that race, and it was the third men's world record in less than four years. That left me wondering: is it just a few exceptional athletes pulling ahead, or is everyone getting faster?
💡 Chart implementation notes
Chart type: This type of chart is typically called a strip plot. Here implemented using a Datawrapper scatter plot, a chart type that allows plotting points positioned freely in 2D space.
The data shape: The x-axis data is the finish time (in seconds) per top-50 finisher each year, and the y-axis data is the year that it happened, with some computationally added jittered offset, so that dots clustered around the same x-position can be discerned. The jitter distance is limited to 45% of the available space for the year, to create a visible gap between years.
GOLDEN_RATIO = 0.618
ROW_HEIGHT = 0.45 # dots spread over 45% of the space between two years
# number the runs within each year, fastest first
df = df.sort_values(["year", "time"])
n = df.groupby("year").cumcount()
# golden-ratio steps give each dot a position between 0 and 1;
# neighbours in time land far apart, so the row fills evenly
position = (n * GOLDEN_RATIO) % 1
# centre the band on the year
df["y"] = df["year"] + (position - 0.5) * ROW_HEIGHTEmbellishments: The custom lines and areas feature is used to draw rectangles behind the data for each row, and text annotations are used to put grid labels above and below the chart.
Looking at the finish times for the top 50 finishers per year, a clear pattern emerges. Among both men and women, elite runners are getting collectively faster. Back in 2000, the men’s world record stood at 2:05:42. Nobody beat it that year. In 2025, all top 50 finishes were faster than that.
Notably, the biggest shifts started to appear around 2017. That’s attributed to a number of factors, like better fuelling, pacing, and training. Although likely the biggest factor is the release of Nike's carbon-plated "super shoes" that year (the Vaporfly), an innovation other brands quickly replicated. The theory is backed by a New York Times analysis of hundreds of thousands of races tracked on Strava, which found the shoes appear to improve finish times by up to 5%³.
The number everyone else is chasing
As for the other tens of thousands of lowly mortals people lining up at a big city marathon, the time to beat isn't 2:00, but a humble 4:00.
These are the finishing times of every runner at the World Marathon Majors in 2025. And in every one of these races, there's a pile-up just before the four-hour mark — followed by a steep drop right after it. In Tokyo, almost twice as many people finished in the five minutes before 4:00 as in the five minutes after.
Consider it a testament to the powerful psychology of round numbers, and their potent speed-boosting properties.
When the number is your ticket
The data for the Boston Marathon in the chart above looks a little different than the others. There’s also a drop at 4:00, but many runners finish well before that. That comes down to Boston’s strict entry requirements¹. To get a spot, runners need a qualifying time from another marathon. That makes it a race full of top-tier runners. So, how has that developed over time?
💡 Chart implementation notes
This type of chart is called a ridgeline plot, a more niche chart type that Datawrapper currently doesn’t offer an out-of-the-box solution for. I recreated the effect with a Datawrapper line chart:
The data shape: Each year is a line (= a column in the dataset), where the data corresponds to the share of finishers per minute + a fixed offset per year, to separate the years
The areas: To create the filled areas, an additional line at each year’s ‘baseline’ is included in the dataset, set to 0 width, and an area fill is added between it and the corresponding data line
Text annotations are doing some heavy lifting: Used for the years on the left, the horizontal grid labels at the top, and the median-time chips on the right (using inline CSS styling for the shading)
In a race full of top-tier runners, a pile-up at the three-hour mark emerges, and it seems to be growing. This year, more Boston runners finished at 2:59 than in any other minute.
The distribution also appears to be shifting to the left, another indication that runners are getting faster. This can also be attributed to increasingly tough entry requirements², although that in itself is likely a response to the pool of eligible runners getting larger as everyone gets faster.
Of course, the year-to-year comparison isn’t perfect. Weather also plays a role — in 2004 and 2012 the temperature reached 30ºC (86°F) and 32ºC (90°F) respectively, pushing the median finish time beyond four hours. And from 2007 onwards, the race start time was brought two hours earlier to 10:00 a.m. (= cooler temperatures), which likely also improved the runners’ outlooks.
But with all that said, I think we can safely conclude that, however we look at the data, two things are clear: runners are getting faster, and people love zeros.
That's it from me this time! Not sure I’ll be shooting for any of those records any time soon, but all the best to anyone running in the upcoming New York City Marathon on November 1st! Stay tuned for next week’s edition, where you'll be hearing from Jack from the development team.



