Anaerobic threshold calculator
At 30 years old with a resting heart rate of 60, your estimated anaerobic threshold is 170.5 beats per minute: 85% of the reserve between rest and an estimated maximum of 190, added back to your resting rate. 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
- Hr max
- 190 bpm
- Hrr
- 130
- Intensity percent
- 85
- Threshold
- 170.5
Anaerobic threshold is the heart rate at which lactate production begins to outpace clearance, so effort above that pace cannot be sustained for long. Coaches and endurance athletes look up this number to set tempo, threshold, and interval sessions without a laboratory lactate test. This calculator estimates anaerobic threshold heart rate in beats per minute from age and resting heart rate using the Karvonen reserve method: maximum heart rate is two hundred twenty minus age, reserve is maximum minus resting rate, and the threshold is resting rate plus eighty-five percent of that reserve. Resting heart rate must be a positive number; otherwise the task fails with invalid input and is not billed.
How the Karvonen method estimates anaerobic threshold heart rate
Anaerobic threshold, also called lactate threshold in many coaching rooms, is the heart rate at which the body shifts from work that can be held for a long time toward work that accumulates fatigue quickly. Laboratory tests measure blood lactate at stepped paces; most runners, cyclists, rowers, and team-sport athletes never see a lab, so they need a field estimate from numbers they already collect. The Karvonen heart-rate reserve method supplies that estimate without asking for a custom intensity percentage.
First it predicts maximum heart rate as two hundred twenty minus age in years, the classic Fox-Haskell shortcut taught in exercise-science courses. Then it subtracts resting heart rate, usually taken seated after several quiet minutes, often first thing in the morning, to obtain heart-rate reserve—the usable gap between rest and maximum. Anaerobic threshold is placed at eighty-five percent of that reserve: the calculator adds eighty-five percent of reserve back onto resting rate and reports the result in beats per minute.
That eighty-five percent convention is the usual Karvonen stand-in for threshold intensity, sitting above easy aerobic work and below all-out intervals. Because this landing is built for the search anaerobic threshold, intensity is not a free parameter here; a custom percentage belongs on a general target-heart-rate tool, and a five-zone chart belongs on a heart-rate-zone tool.
Age and resting heart rate are the only required inputs, and the arithmetic never consults a network, a clock, or a random generator, so the same pair of numbers always yields the same threshold in beats per minute.
How to use it in training and its limits
Call the free in-browser anaerobic threshold calculator for gym-floor demos, PE labs, and quick athlete checks without rebuilding reserve arithmetic in every spreadsheet. Pair a consistent morning resting measurement with age, store threshold beside tempo and cruise-interval prescriptions, and remember that two hundred twenty minus age is only a population estimate—true maximum varies with genetics, medication, and sport, and this calculator does not accept a lab-measured maximum override.
It is not a diagnostic medical device, not a five-zone Karvonen chart, and not a custom-intensity target-heart-rate solver: those are different search intents with their own landings. People with cardiac conditions, medications that alter heart rate, or physician restrictions should follow professional advice rather than any single formula alone.
What you can do with it
Endurance coaching and tempo session cards
Coaches enter athlete age and morning resting heart rate to print an anaerobic threshold in bpm on tempo and cruise-interval cards without a lactate lab.
FAQ
How is anaerobic threshold heart rate calculated here?
The result is returned in beats per minute.
Why is intensity fixed at 85% of heart-rate reserve?
Eighty-five percent of Karvonen reserve is the usual field stand-in for anaerobic / lactate-threshold intensity. This landing does not take a custom percentage; that is a different calculator.
What happens if resting heart rate is not a positive number?
Resting heart rate must be a positive finite number strictly below estimated maximum (220 − age). Zero, negative, and non-numeric values are rejected and not billed.
Is the anaerobic threshold 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/sports/anaerobic-threshold \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"age":30,"resting_hr":60}'const res = await fetch("https://api.kit.forhosting.com/sports/anaerobic-threshold", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"age": 30,
"resting_hr": 60
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/sports/anaerobic-threshold",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"age": 30,
"resting_hr": 60
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/sports/anaerobic-threshold", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"age":30,"resting_hr":60}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"age":30,"resting_hr":60}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/sports/anaerobic-threshold", 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
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "sports.anaerobic_threshold",
"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
Inputs, outputs, and when the calculator rejects a request
Age must fall between one and one hundred twenty years so the Fox estimate of maximum heart rate stays in a usable band. Resting heart rate must be a positive number—greater than zero and finite. The unit field is always bpm, formula restates the Karvonen identity, and method is always karvonen so downstream code can branch without sniffing shapes. Example: age thirty and resting sixty yields maximum one hundred ninety, reserve one hundred thirty, and threshold one hundred seventy point five beats per minute, because sixty plus eighty-five percent of one hundred thirty is one hundred seventy point five. Send a JSON body with two required finite numbers: age in years and resting_hr in beats per minute. Age may also arrive as years or age_years; resting rate accepts resting, rhr, rest_hr, resting_heart_rate, and hr_rest. Zero, negative values, empty strings, and non-numeric text all fail with invalid_input, and those failures are not billed. Resting rate must also sit strictly below estimated maximum (two hundred twenty minus age); otherwise reserve would not be positive and the request is rejected with a message that names both rates. On success the body echoes age and resting_hr, then hr_max, hrr (heart-rate reserve), intensity_percent which is always eighty-five, and threshold—the anaerobic threshold in beats per minute, rounded to one decimal for stable goldens. Use threshold on a watch or session card; use hr_max and hrr when you want to show the intermediate steps students learn on paper.
Training use, API pricing, and what this number is not
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. Authors shipping SDKs can map threshold, hr_max, and hrr into dashboards and export columns for age, resting rate, and anaerobic threshold in bpm—the same numbers coaches compute by hand after measuring a resting pulse.
Integration use cases
PE classes and sports-science homework
Students compute Karvonen anaerobic threshold from age and resting HR and pin the deterministic JSON in automated checkers instead of grading by hand.
Wearable and training-log backends
Apps that already store resting HR call a prepaid endpoint for threshold bpm instead of duplicating Fox 220−age and eighty-five percent reserve in every language.