Skip to content
Race-time prediction for cyclists with power meters

Predict your race time.

Free foreverOpen sourceNo account to plan

Plan a goal event from a route, your rider numbers, and the group you expect to ride in. Get a finish-time ceiling (the best you could ride at the effort you set, not a promise) plus per-split target watts for your head unit: Garmin Power Guide overlay or FIT Workout for Wahoo, Hammerhead, and Bryton.

Built for amateurs. Validated on pro rides because public power data lives there.

Pick a route

Your numbers

Physics only: your ride, your declared shelter, no race tactics.

Sex

Not set: the model assumes male physiology (W′ scaling, W/kg tiers) until you pick.

Ride type

Auto: picked from the route when you plan (TT course → TT pacing, everything else → sportive).

Plan and preview without an account; email magic-link sign-in is needed only to download the FIT, a lightweight gate that keeps automated abuse out.
Or analyze a past ride →

The model tracks the pacing curve across the course, not just the finish: intermediate checkpoints land within tens of seconds of Remco's real splits. The finish time is a ceiling for the effort you set, not a promise of what you will do. Details on Methodology.

How accurate is this?

Mean finish-time error · lower is better
3.2%
Pros going for the win (11 races). 91% land within 5%.
4.9%
Amateurs going for the win (5 races). Same physics, your profile.

Mean finish-time error over the whole ride. On flat, gravel and cobbled roads the per-split watts land within a few watts of what the rider actually did: flat sits at +3 W for pros, +8 W for amateurs.

You give it the effort, the group you expect to ride in, and your CdA. It doesn't read your tactics from a cohort and it doesn't guess. Give it the full set and it lands at 3 to 5%. The rides where it's looser are the ones where a rider sat in a draft the model was never told about: that draft is yours to supply, and the number tightens when you do. Full breakdown by tier, goal and terrain →

Custom-course uploads are end-to-end encrypted. The AES key lives in the URL fragment (the part after #), which browsers don't send to the server. Only someone with the full link can decrypt the route. The server only ever sees ciphertext. Privacy →

Run it locally

Open source, MIT. Repo flips public with the v1.0 SemVer commit (PyPI publish lands the same day). Until then the link 404s; the install path will work the moment the repo flips.

git clone https://github.com/sam-dumont/bike-power-model-lib
cd bike-power-model-lib
uv sync --extra api --extra analysis
uv run bpm --help

Full install + license + integration notes on Developers.

Why this exists

One thing led to another. The original goal was a single Paris-Roubaix Challenge: prep a plan, write it onto the Edge as a Garmin Power Guide, ride. Turned out the two FIT messages behind Power Guide (352 and 353) weren't documented publicly, so they had to be reverse-engineered from binary dumps before anything else.

Once the format was writable, what to write was the next problem. Garmin's native plan only sees gradient: not Arenberg cobble, not a 33 km/h Zeeland headwind, not the mud-slick descent out of La Redoute. So the next step was a Martin-1998 power balance to drive better targets. Then per-surface Crr because cobble isn't tarmac, asymmetric wind because real weather isn't uniform, declared shelter because solo, paceline, and bunch aren't the same aero problem. Heat / altitude / fatigue / sector-aware rain decay piled on after. A long thread of "OK the prediction is wrong on this stage, why?" → fix → next stage. Methodology →