Target heart rate Karvonen calculator
A 30-year-old with a resting pulse of 60 who trains at 70% of reserve should aim for 151 beats per minute. Enter your age, resting heart rate and intensity to get your own single target. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Age
- 30
- Resting heart rate
- 60
- Intensity
- 70
- Intensity percent
- 70 bpm
- Intensity fraction
- 0.7
- Hr max
- 190
- Hrr
- 130
The Karvonen formula estimates a personal training heart rate from three simple numbers: your age, your resting heart rate, and the intensity you want as a percentage of heart-rate reserve. Unlike a flat percentage of maximum heart rate alone, the reserve method first subtracts resting rate from estimated maximum, then scales that reserve by intensity and adds resting rate back, so people with different resting baselines get different targets at the same intensity label.
What the Karvonen reserve method measures and which inputs you need
Heart-rate training zones help runners, cyclists, and general fitness clients work at a controlled intensity without a lab stress test. The Karvonen heart-rate reserve method starts from an estimated maximum heart rate of two hundred twenty minus age in years, a simple Fox-Haskell style estimate widely taught in coaching courses. Resting heart rate is usually measured after several minutes of quiet sitting, often first thing in the morning, and is expressed in beats per minute.
Intensity is the fraction of the gap between resting and maximum that you want to work at: fifty percent of reserve is a light aerobic effort for many people, while seventy to eighty-five percent is a common vigorous range, always depending on fitness and medical context. Intensity may be a percentage from zero to one hundred or a fraction from zero to one inclusive, so seventy and zero point seven both mean seventy percent of reserve. Age must fall in a practical one-to-one-hundred-twenty year band.
What you can do with it
Gym programming and personal training apps
Trainers enter client age, resting HR, and zone intensity to show a Karvonen target bpm on session cards without reimplementing reserve math in each client.
FAQ
What is the Karvonen target heart rate formula?
Intensity is a fraction of reserve (for example 0.7 or 70%).
What happens if resting heart rate exceeds maximum?
Resting rate must be strictly below estimated HR_max (220 − age); when resting meets or exceeds maximum, reserve is not positive and the calculator rejects the input without charging.
Can I send intensity as 70 or as 0.7?
Yes. Values from 0 to 1 inclusive are treated as fractions of reserve; values above 1 up to 100 are treated as percentages. Both 70 and 0.7 mean 70% of heart-rate reserve.
Is the target heart rate Karvonen calculator free?
The browser tool runs free on your device.
Is 220 minus age the true maximum heart rate?
No. It is a simple population estimate used for educational and planning purposes. True maximum varies by individual; this product does not accept a lab-measured HR_max override.
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/target-hr-karvonen \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"age":30,"resting_hr":60,"intensity":70}'const res = await fetch("https://api.kit.forhosting.com/health/target-hr-karvonen", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"age": 30,
"resting_hr": 60,
"intensity": 70
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/health/target-hr-karvonen",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"age": 30,
"resting_hr": 60,
"intensity": 70
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/health/target-hr-karvonen", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"age":30,"resting_hr":60,"intensity":70}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"age":30,"resting_hr":60,"intensity":70}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/health/target-hr-karvonen", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"age": 30,
"resting_hr": 60,
"intensity": 70
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "health.target_hr_karvonen",
"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
This capability applies HR max equals two hundred twenty minus age, computes reserve, multiplies by intensity, and returns structured JSON with maximum HR, reserve, target bpm, and both percent and fraction forms of intensity. The path is pure arithmetic with no network and no random seed, so coaching apps, PE labs, and prepaid API clients get identical results every time. When resting heart rate meets or exceeds the estimated maximum, the request fails with invalid input because reserve cannot be zero or negative for a meaningful Karvonen target.
What the Karvonen reserve method measures and which inputs you need
Send required fields age, resting_hr, and intensity as finite numbers; aliases years and age_years work for age, resting, rhr, rest_hr, resting_heart_rate, and hr_rest work for resting rate, and intensity_percent, percent, pct, intensity_pct, and target_percent work for intensity. Identical inputs always yield identical JSON because the algorithm never touches the network, a model, a clock, or a random generator. Missing fields, non-finite values, out-of-range age or intensity, and resting rates that meet or exceed estimated maximum all fail with invalid_input and are not charged.
Reading the response fields and interpreting target heart rate
Remember that two hundred twenty minus age is only an estimate—true maximum varies with genetics, medication, and sport, and this calculator does not accept a custom measured maximum. On success the response echoes age and resting_hr, then intensity_percent and intensity_fraction so UIs can show either form without recomputing. The field hr_max is estimated maximum heart rate as two hundred twenty minus age, hrr is heart-rate reserve as hr_max minus resting_hr, and target_hr is the Karvonen target in beats per minute: resting plus intensity times reserve. The unit field is always bpm, formula restates the reserve equation, and method is always karvonen_reserve so downstream code can branch without sniffing shapes. Use target_hr for a single training number on a watch or console; use hr_max and hrr when you want to show the intermediate steps students learn on paper; use intensity_fraction when chaining zone logic that already works on zero-to-one scales. Resting heart rate that equals or exceeds estimated maximum is impossible for a positive reserve and raises a clear invalid_input message that mentions resting rate exceeding maximum. Do not confuse this endpoint with pure percentage-of-max formulas that ignore resting rate, with lactate-threshold zones, or with clinical stress-test targets: those are different intents.
API usage, pricing, coaching workflows, and practical limits
Call the free in-browser target heart rate Karvonen calculator for PE classes, gym floor demos, and quick client checks without rebuilding the reserve arithmetic in every spreadsheet. Prefer consistent morning resting measurements; if your UI collects intensity only as whole percents, send seventy rather than zero point seven—the engine accepts both. Keep expectations educational: this is a planning and learning tool, not a diagnostic medical device, and people with cardiac conditions, medications that alter heart rate, or physician restrictions should follow professional advice rather than any single formula alone. Send a JSON body with required age, resting_hr in beats per minute, and intensity as a percent or fraction. Use the prepaid API when a coaching SaaS, wearable companion, school LMS, or training log 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 resting-rate measurement workflow, then store target_hr alongside zone labels for warm-up, aerobic base, and tempo sessions. Authors shipping SDKs can map target_hr, hr_max, and hrr into dashboards and export CSV columns for age, resting rate, intensity, and Karvonen target—the same numbers coaches compute by hand after measuring a resting pulse.
Integration use cases
PE classes and sports science homework
Students compute target heart rates for 50%, 70%, and 85% of reserve and pin expected JSON in automated checkers with deterministic Karvonen outputs.
Wearable and coaching SaaS backends
Server pipelines that already store resting HR call a prepaid endpoint for target_hr instead of duplicating Fox 220−age and reserve formulas in every language.