Cycling calorie calculator
A 70 kg rider at moderate effort for 60 minutes burns about 476 kcal, using MET 6.8 times weight times hours. Enter distance, time or both, pick an intensity from light to racing, and log the estimate. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Weight (kg)
- 70
- Intensity
- moderate
- Ride distance in kilometres
- 20
- Ride duration in minutes
- 60
- Met
- 6.8 kcal
- Duration hours
- 1
- Duration source
- provided
- Calories kcal
- 476
Planning a bike commute, a weekend loop, or a training block often starts with a simple question: how many calories does this ride burn? This cycling calorie calculator answers with a transparent metabolic-equivalent method: multiply a published cycling MET by body weight in kilograms and by ride duration in hours. You can supply ride distance, ride duration, or both, plus an intensity band from light leisure spinning to racing pace. Non-positive body weight is rejected as invalid input because a zero or negative mass cannot define energy cost.
What the calculator measures and which inputs you need
Calories burned cycling are reported as kilocalories using the classic MET formula calories equals MET times body weight in kilograms times duration in hours. A MET, or metabolic equivalent of task, scales energy cost relative to quiet sitting; higher intensity bands carry higher MET values drawn from Compendium-style cycling categories. Send intensity as light, moderate, vigorous, or racing, case-insensitive, with friendly synonyms such as easy, leisurely, hard, medium, and race; the default when omitted is moderate.
When only distance is given, the engine estimates duration from a typical cruising speed for that intensity band so a single distance field still yields a complete calorie estimate. When only duration is given, calories use that time directly. When both are given, the provided duration drives the formula and average speed is reported from distance over hours.
Missing weight, missing both distance and duration, non-finite numbers, and unrecognized intensity labels all fail validation.
What you can do with it
Commute and weekend ride planning
Riders enter body weight, planned kilometres, and an intensity band to estimate kilocalories before packing snacks or logging the ride in a journal.
FAQ
What happens if weight is zero or negative?
Body weight must be a positive number in kilograms; non-positive values are rejected and not charged.
Is the cycling calorie calculator free?
The browser tool runs free on your device.
Which intensity MET values are used?
Light uses MET 4.0, moderate 6.8, vigorous 10.0, and racing 12.0, aligned with common Compendium-style cycling categories for transparent educational estimates.
Can I enter only the distance of my ride?
Yes. If you give distance but no time, the ride duration is estimated from a typical cruising speed for the intensity you chose, so a single distance still gives a full calorie estimate.
Why might my real calories differ from the estimate?
Wind, hills, riding in a group's slipstream, the weight of the bike and your own pedalling economy all change real energy use. Treat the figure as an estimate, not a lab measurement.
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/health/cycling-calories \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"weight_kg":70}'const res = await fetch("https://api.kit.forhosting.com/health/cycling-calories", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"weight_kg": 70
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/health/cycling-calories",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"weight_kg": 70
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/health/cycling-calories", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"weight_kg":70}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"weight_kg":70}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/health/cycling-calories", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"weight_kg": 70
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "health.cycling_calories",
"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.
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
The path is pure deterministic arithmetic with no network calls, no random seed, and no wall clock, so coaching apps, fitness journals, and prepaid API clients receive identical JSON every time for the same inputs.
What the calculator measures and which inputs you need
Send weight_kg as a positive finite number; aliases weight, body_weight, mass_kg, and bodyweight_kg are accepted. Zero or negative weight fails with invalid_input and is not charged. Provide at least one of distance_km or duration_min as a positive finite number. Distance aliases include distance, km, and ride_km; duration aliases include duration, minutes, time_min, and ride_minutes. Identical inputs always yield identical JSON because the algorithm never touches the network, a model, a clock, or a random generator.
Reading the response fields and intensity MET bands
Do not treat the figure as a medical diagnosis or a lab-grade calorimetry result: wind, hills, drafting, bike mass, and individual economy all move real expenditure. Extremely large weights, distances, or durations above published isolate safety caps are rejected. On success the response echoes weight_kg and the normalized intensity label so clients can confirm what was computed. The field met is the numeric metabolic equivalent used: four point zero for light leisure riding, six point eight for moderate steady riding, ten for vigorous hard efforts, and twelve for racing pace. duration_min and duration_hours report the time that entered the formula; duration_source is either provided when you sent minutes, or estimated_from_distance when only kilometres were available. calories_kcal is the headline energy estimate in kilocalories, unit is always kcal, formula restates the MET equation, and method is always met_cycling_compendium so downstream code can branch without sniffing shapes. When distance was supplied, distance_km is echoed; when both distance and a usable duration exist, average_speed_kmh is included. If duration was estimated from distance alone, assumed_speed_kmh shows the cruise speed table value used for that intensity band. Use calories_kcal for journals and meal offsets; use met and duration_hours when you want to re-derive the math in a spreadsheet.
API usage, pricing, training workflows, and practical limits
Call the free in-browser cycling calorie calculator for commute planning, group-ride estimates, lecture demos, and quick mental checks without installing a training spreadsheet. Prefer body weight that matches your product’s user profile units after converting pounds to kilograms on the client. Keep expectations educational: this is a planning and literacy tool, not a diagnostic medical device, and riders with clinical needs should follow professional guidance rather than any single formula alone. Send a JSON body with required weight_kg, optional intensity, and at least one of distance_km or duration_min (or their aliases). Use the prepaid API when a fitness SaaS, bike-computer companion app, wellness coach portal, or route planner needs a stable contract under KIT balance at $0.002 per successful item; validation failures never consume balance after the engine rejects the request. Pair this endpoint with your own GPS logs: pass measured minutes when you have them for tighter estimates, or pass planned kilometres with an intensity band when you are still building the route. Authors shipping SDKs can map calories_kcal, met, and duration_hours into dashboard cards and export CSV columns labeled ride energy and MET band—the same numbers coaches write by hand when they apply MET tables on paper.
Integration use cases
Fitness and coaching apps
Apps that store user weight and ride summaries call a stable prepaid endpoint for MET-based cycling calories instead of reimplementing intensity tables in every client language.
Classroom and public-health demos
Courses compare light versus vigorous MET bands for the same distance, show duration estimation from cruise speed, and pin expected JSON in automated tests.
Technical questions
How do I calculate calories burned cycling?
Send JSON with weight_kg and at least one of distance_km or duration_min. Optional intensity defaults to moderate. The response includes calories_kcal from MET × weight × hours.
Can I send only distance without duration?
Yes. When duration_min is omitted, the engine estimates ride time from a typical cruising speed for the chosen intensity band and sets duration_source to estimated_from_distance.