EV Battery Degradation Calculator
An electric vehicle battery gradually loses usable capacity, which can reduce the distance available from a full charge.
Run — free
This calculator estimates that change from the battery's original usable size, its original driving range, an expected annual degradation rate, and years of use. It reports retained capacity, lost capacity, remaining kilowatt-hours, and proportional range. The calculation is deterministic and useful for comparisons, budgeting, and long-term planning, but it does not replace a vehicle-specific battery health test.
Enter comparable starting values
Start with the vehicle's original usable battery capacity, not necessarily the larger gross capacity advertised for the physical pack. Manufacturers may reserve energy buffers that drivers cannot access, so gross and usable figures can differ. Then enter an original range measured under a consistent basis. An official test-cycle rating is suitable when you want to estimate how that same rating might change, while a personal warm-weather baseline is better for comparing your own driving. Avoid mixing an official laboratory range with a recent winter observation, because temperature, cabin heating, speed, wind, elevation, tire pressure, and driving style can move range independently of degradation. The annual degradation rate is expressed as a percentage of the capacity remaining at the beginning of each year. Years may include a fractional part, which is helpful for a vehicle that is, for example, four and a half years old. Keeping the starting capacity and range on comparable terms makes the output easier to interpret and avoids attributing ordinary efficiency differences to battery aging.
Understand the compounded calculation
The calculator uses geometric compounding. For an annual degradation rate r and an age y, the retained fraction is calculated as (1 - r) raised to the power y. Remaining battery capacity equals the original usable capacity multiplied by that retained fraction. Estimated range is calculated by multiplying the original range by the same fraction. This means a two percent annual rate does not simply remove twenty percent over ten years: each year's loss is applied to a slightly smaller remaining capacity. The output includes both retention and loss percentages, remaining and lost kilowatt-hours, and estimated remaining and lost range. Results are rounded to six decimal places for stable reporting, although the precision of the estimate is limited by the assumptions you enter. A constant annual rate is a simplified planning model. Real packs may degrade faster early in life, settle into a slower period, and change again with age, mileage, charging habits, thermal exposure, chemistry, or individual cell condition.
Use the result as a scenario, not a diagnosis
Treat the estimate as a controlled scenario for answering questions such as whether an older vehicle could still cover a commute or how much usable energy might remain near the end of an ownership period. It is especially useful for comparing several degradation assumptions: run a conservative rate, a middle estimate, and an optimistic rate while holding the starting values constant. The resulting range assumes energy consumption per kilometer stays unchanged. In real driving, efficiency can vary enough to outweigh modest battery degradation, so a lower observed range alone does not prove that the battery has lost the same percentage of capacity. For a vehicle-specific assessment, consult its battery management system data, a qualified diagnostic report, or a repeatable full-charge energy test. Also check how the manufacturer defines state of health and warranty thresholds, because those definitions may not match this simple usable-capacity model. The API price is $0.002 per request, and the same deterministic calculation can support repeatable planning tools and ownership comparisons.
What you can do with it
Evaluate a used EV
Compare plausible degradation scenarios to estimate whether the vehicle's remaining range fits regular journeys before arranging a diagnostic inspection.
Plan long-term ownership
Estimate usable battery capacity and range at a future ownership milestone while keeping the original vehicle assumptions consistent.
Compare battery aging scenarios
Run optimistic, typical, and conservative annual rates to see how compounded degradation changes capacity and range over time.
FAQ
What does the calculation cost?
Each API request costs $0.002. The calculation uses one input item and has no usage-based unit charge.
Does battery degradation compound each year?
Yes. The entered rate is applied to the capacity remaining at the start of each year rather than repeatedly subtracting the same number of kilowatt-hours.
Should I enter gross or usable battery capacity?
Use original usable capacity when available, because that is the energy accessible for driving and is the most meaningful basis for a range estimate.
Why might real-world range differ from the result?
Weather, speed, elevation, tires, cabin conditioning, payload, driving style, and measurement method all affect energy consumption independently of battery capacity.
Is this a battery state-of-health test?
No. It is a mathematical scenario based on a constant annual rate. A diagnostic reading or controlled capacity test is needed to assess a specific battery.
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/travel/ev-battery-degradation \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"original_battery_kwh":75,"annual_degradation_percent":2.3,"years":8,"original_range_km":480}'const res = await fetch("https://api.kit.forhosting.com/travel/ev-battery-degradation", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"original_battery_kwh": 75,
"annual_degradation_percent": 2.3,
"years": 8,
"original_range_km": 480
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/travel/ev-battery-degradation",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"original_battery_kwh": 75,
"annual_degradation_percent": 2.3,
"years": 8,
"original_range_km": 480
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/travel/ev-battery-degradation", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"original_battery_kwh":75,"annual_degradation_percent":2.3,"years":8,"original_range_km":480}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"original_battery_kwh":75,"annual_degradation_percent":2.3,"years":8,"original_range_km":480}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/travel/ev-battery-degradation", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"original_battery_kwh": 75,
"annual_degradation_percent": 2.3,
"years": 8,
"original_range_km": 480
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "travel.ev_battery_degradation",
"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. |