Bike pace calculator
40 kilometres in two hours is 20 km/h and 3:00 per kilometre: the two figures cyclists quote, from the distance and time your ride computer already shows. Compare a club 40k, a gran fondo and a trainer session on one scale. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Distance
- 40
- Time seconds
- 7,200
- Time hours
- 2
- Speed kmh
- 20
- Pace s per km
- 180
- Pace per km
- 3:00
A bike pace calculator turns the two numbers every ride computer already has — kilometres covered and elapsed moving time — into the pair cyclists actually quote: average speed in kilometres per hour, and time per kilometre. Enter how far you rode or plan to ride and how long the clock ran; the tool returns km/h, seconds per kilometre, and a readable mm:ss per kilometre so you can compare a club 40k, a gran fondo, or a winter trainer session on the same scale.
What bike pace means for cyclists and how the two numbers relate
Cyclists almost never talk about a ride the way runners talk about a 10k. The native language on the road, on a sportive start line, and on a club WhatsApp thread is average speed in kilometres per hour: twenty-eight km/h on a rolling 60k, thirty-two km/h on a flat 40k, eighteen km/h up a long alpine valley.
Time per kilometre is the same information written as a clock instead of a velocity: twenty-five kilometres per hour is exactly two minutes twenty-four seconds per kilometre, because one hour contains three thousand six hundred seconds and three thousand six hundred divided by twenty-five is one hundred forty-four seconds. That dual view is useful when you are matching a climbing split, writing a cue sheet, or comparing a trainer block that reports km/h with a road loop that your computer stored as elapsed time and distance.
The identities are elementary and must stay elementary: average speed in km/h equals distance in kilometres divided by elapsed hours, and seconds per kilometre equals elapsed seconds divided by distance in kilometres. This calculator does not guess wind, draft, or gradient, and it does not read a FIT file. You pass the two scalars you already trust from the head unit, the indoor trainer, or the route plan, and it returns both views of the same average.
Zero or negative distance would make time per kilometre infinite; zero or negative elapsed time would make speed infinite. Forty kilometres in two hours is twenty km/h and three minutes per kilometre — the honest average of that clock, not a peak, not a normalized power, and not a predicted speed from watts.
Where a deterministic bike pace calculator earns its keep
Club secretaries printing a 40k handicap sheet need the same km/h and min/km for every rider from the same two inputs, not a spreadsheet cell someone edited during a rain delay. Gran-fondo and brevet planners convert a target distance and a target elapsed time into the average they will write on the briefing: 180 kilometres in seven hours is a very different day from 180 kilometres in ten, and both should be computed, not guessed.
Indoor-trainer dashboards that already store kilometres and moving seconds can fill an average-speed column without standing up a cycling-data vendor. Failed validation does not consume balance. Keep distance and time in the same ride window — do not divide this morning's kilometres by last week's trainer minutes — and you get a reproducible average for cue sheets, LMS quizzes, and edge workers.
This landing is for people searching for a bike pace calculator, cycling average speed, or time per kilometre from a completed or planned clock. It is not a duration estimator from a guessed speed (use a cycling time estimator for that inverse), not a running min/km tool, not a swim pace per 100 m, and not a speed-from-watts predictor. Prefer this capability when you already know how far and how long, and only need km/h and time per kilometre.
What you can do with it
Club 40k and sportive briefing cards
Turn a planned route distance and a target elapsed time into km/h and min/km so riders on mixed computers share one average.
Training-log average speed
Apps that already store kilometres and moving seconds call this once to fill a deterministic average-speed and time-per-km column.
FAQ
How is bike pace calculated from distance and elapsed time?
Average speed in km/h is distance divided by elapsed hours. Time per kilometre is elapsed seconds divided by distance.
What happens if distance or time is zero or negative?
Average speed is undefined when elapsed time is not positive, and time per kilometre is undefined when distance is not positive. The failure is not billed.
Is this a running pace calculator or a ride-time estimator?
Neither. This landing is cycling pace from a known distance and a known elapsed clock: km/h and time per kilometre. Running min/km and estimating duration from a guessed speed are different searches.
How do I enter a ride time given in hours and minutes?
Convert it to total seconds first. Two hours is 7200 seconds, ninety minutes is 5400 and one hour fifteen is 4500. Then enter that total with the distance in kilometres.
Is the result my peak speed or my average?
It is the plain average of the clock you entered, not a peak, not normalized power and not a speed predicted from watts. Wind, drafting and gradient are not guessed; they are already inside your distance and time.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/sports/bike-pace \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"distance":40,"time_seconds":7200}'const res = await fetch("https://api.kit.forhosting.com/sports/bike-pace", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"distance": 40,
"time_seconds": 7200
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/sports/bike-pace",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"distance": 40,
"time_seconds": 7200
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/sports/bike-pace", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"distance":40,"time_seconds":7200}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"distance":40,"time_seconds":7200}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/sports/bike-pace", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"distance": 40,
"time_seconds": 7200
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "sports.bike_pace",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_distance | 1000000 |
max_time_seconds | 8640000 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
Distance or elapsed time that is zero or negative is rejected with invalid_input, because average speed is undefined when time is not positive and time per kilometre is undefined when distance is not positive.
What bike pace means for cyclists and how the two numbers relate
Both cases fail loudly as invalid_input instead of printing Infinity on a dashboard.
Inputs, formula, rounding, and the non-positive error
Convert hours and minutes before you call: two hours is 7200 seconds, ninety minutes is 5400, one hour fifteen is 4500. Numeric fields are rounded to ten decimal places for stable goldens across runtimes. Example: 40 kilometres in 7200 seconds yields 20 km/h and 180 seconds per kilometre, shown as 3:00 per km. Example: 25 kilometres in 3600 seconds yields 25 km/h and 2:24 per km. Failed validation is not billed. POST a JSON body with two required finite positive numbers: distance, the kilometres covered on the bike, and time_seconds, the elapsed ride time as a total in seconds. Each field may arrive as a JSON number or as a numeric string. Aliases dist, d, km, and distance_km are accepted for the kilometres; aliases time, elapsed, elapsed_seconds, t, and seconds are accepted for the clock. Missing fields, empty strings, NaN, Infinity, and non-numeric text fail with invalid_input naming the field. Distance must be strictly greater than zero and at most one million kilometres; time_seconds must be strictly greater than zero and at most eight million six hundred forty thousand seconds (one hundred days). Those ceilings keep intermediate products finite on the Worker and in the browser. On success the body echoes rounded distance and time_seconds, publishes time_hours so you do not redivide by 3600, returns speed_kmh as the average speed, returns pace_s_per_km as raw seconds per kilometre, and formats pace_per_km as M:SS or H:MM:SS with whole-second rounding on the display string only. The formula field restates speed_kmh = distance / (time_seconds / 3600) and pace_s_per_km = time_seconds / distance so a report can print the identity next to the numbers.
Integration use cases
Indoor trainer and race-simulation gates
Reject a zero-distance or zero-time interval as invalid_input instead of rendering Infinity km/h on a dashboard after a paused block.
Technical questions
Do I send time as hours and minutes?
No. Send total elapsed time as time_seconds (for example 7200 for two hours, 5400 for ninety minutes). The response includes time_hours and a formatted pace_per_km string.
What does the bike pace calculator cost?
The browser tool is free. API requests use prepaid KIT balance at $0.002 per successful call; invalid input is not billed.