Smoking recovery
Enter your quit date, how many years you smoked and a reference date to see how much of the extra lung-cancer risk caused by smoking has faded: 20 years smoked and 10 years since quitting means just over three quarters of that excess gone. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Quit date
- 2016-07-25
- Years smoked
- 20
- As of
- 2026-07-25
- Days since quit
- 3,652
- Years since quit
- 9.9988363895
- Remaining excess fraction
- 0.2419577581
- Risk reduction pct
- 75.8042241857
A smoking recovery calculator estimates how much of the smoking-attributable excess lung-cancer risk has declined since a person quit. Enter the quit date, how many years they smoked before stopping, and a reference calendar date; the tool converts the calendar gap into years since cessation with a proleptic Gregorian day count, then applies the Doll–Peto duration-power model with Armitage–Doll cessation decay. The remaining excess fraction is years smoked divided by years smoked plus years since quit, raised to 3.5, and the estimated risk reduction percentage is one hundred times one minus that fraction.
What excess-risk recovery means after quitting smoking
Continuing smokers carry an excess lung-cancer risk that grows steeply with how long they have smoked. Doll and Peto showed that incidence among continuing smokers is approximately proportional to duration raised to about 4.5; that duration-power identity is the backbone of many educational cessation models. After a person stops, the excess does not vanish on the quit day: the remaining fraction of that excess is commonly written as duration at cessation divided by duration plus time since quit, raised to k minus one.
With k equal to 4.5 the exponent is 3.5, so someone who smoked twenty years and quit ten years ago keeps roughly (20 / 30) to the 3.5 of their peak excess, which is about a three-quarter drop in the smoking-attributable extra risk—not a statement that they now have the same absolute risk as a lifelong never-smoker, and not a personal diagnosis.
Time since quit is a calendar quantity: this calculator counts whole Gregorian days from the quit date to the reference date and divides by the mean Gregorian year 365.2425, so leap days are included without ever reading the server clock. Zero years smoked is allowed and yields zero percent reduction because there is no smoking-attributable excess to recover; a quit date equal to the reference date likewise yields zero percent because no recovery time has elapsed.
The output always includes the remaining excess fraction, the estimated risk reduction percentage, days and years since quit, the Doll–Peto k, a formula string, and ordered substitution steps you can pin in tests or worksheets.
What you can do with it
Quit-smoking education worksheets
Counsellors enter a quit date, years smoked, and today's worksheet date to show an estimated excess-risk reduction percentage with substitution steps.
Personal progress from a known quit date
Someone who quit on a recorded day can compare estimated recovery at one, five, and ten years without a spreadsheet or a clinical risk engine.
FAQ
How is lung-cancer risk recovery after quitting calculated?
Risk reduction percent is 100 × (1 − remaining excess).
What if years smoked is negative?
Negative duration is not a valid smoking history; zero years smoked is allowed and yields 0% reduction because there is no excess to recover.
Is this a medical diagnosis or a clinical lung-cancer risk score?
No. It is an educational Doll–Peto duration-power estimate of excess-risk recovery. It does not replace PLCOm2012, LLP, Bach, screening criteria, or a clinician's judgement.
What does the smoking recovery calculator cost?
The browser tool is free and runs locally.
Does a large drop mean my risk now matches a never-smoker's?
No. The figure is how much of the extra risk caused by smoking has faded, not your absolute risk. It does not say you are now level with someone who never smoked, and it is not a personal diagnosis.
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/smoking-recovery \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"quit_date":"2016-07-25","years_smoked":20,"as_of":"2026-07-25"}'const res = await fetch("https://api.kit.forhosting.com/health/smoking-recovery", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"quit_date": "2016-07-25",
"years_smoked": 20,
"as_of": "2026-07-25"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/health/smoking-recovery",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"quit_date": "2016-07-25",
"years_smoked": 20,
"as_of": "2026-07-25"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/health/smoking-recovery", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"quit_date":"2016-07-25","years_smoked":20,"as_of":"2026-07-25"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"quit_date":"2016-07-25","years_smoked":20,"as_of":"2026-07-25"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/health/smoking-recovery", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"quit_date": "2016-07-25",
"years_smoked": 20,
"as_of": "2026-07-25"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "health.smoking_recovery",
"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_years_smoked | 120 |
max_years_since_quit | 120 |
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
Negative years smoked are rejected with invalid_input so a form mistake never invents a recovery curve.
Input contract, dates, and error behaviour
POST a JSON body with three required fields. quit_date (aliases quit, cessation_date, date_quit, stopped_on) is the calendar day the person stopped, as a real Gregorian date in YYYY-MM-DD form with years from one through nine thousand nine hundred ninety-nine; impossible days such as the thirty-first of April are rejected. years_smoked (aliases years, duration_years, smoking_years, years_of_smoking) is the duration of smoking at cessation: a finite non-negative number, zero allowed, at most one hundred twenty. as_of (aliases as_of_date, reference_date, on, date) is the evaluation day, also YYYY-MM-DD, and must fall on or after the quit date so years since quit cannot go negative. On success the body echoes quit_date, as_of, and years_smoked, sets days_since_quit to the integer serial-day difference, years_since_quit to that difference divided by 365.2425, remaining_excess_fraction to the Doll–Peto remaining share, risk_reduction_pct to one hundred times one minus that share, doll_peto_k to 4.5, plus formula, message, and steps. Failed validation—missing fields, non-finite numbers, negative years smoked, a future quit relative to as_of, dates outside the supported year range, or more than one hundred twenty years since quit—returns invalid_input and is never charged. Successful calls cost a flat $0.002 with unit item.
Practical uses, limits, and how this differs from pack-years
Prefer a pack-year tool when you only need cumulative cigarette exposure; prefer this capability when the question is excess-risk recovery as a function of quit date and duration. Keep durations inside the published absolute range so the power cannot overflow. Pair examples deliberately: quit on two thousand sixteen July twenty-fifth, as_of two thousand twenty-six July twenty-fifth, twenty years smoked for a decade of recovery; forty years smoked with only five years since quit to show that longer duration slows the fractional drop; a negative years_smoked value to demonstrate the hard invalid_input path. This landing targets people searching for a smoking recovery calculator, lung cancer risk after quitting, or how much lung-cancer risk falls when you stop smoking. It is not a pack-years calculator (that product is cigarettes per day times years smoked, a different search intent), not a PLCOm2012 or LLP clinical risk score, not a cotinine converter, and not medical advice for an individual patient. Failed tasks that return invalid_input do not consume prepaid balance. Round-trip checks are easy: recompute days between the two ISO dates, divide by 365.2425, raise D over D plus T to 3.5, and confirm that one hundred times one minus that quantity equals the published risk_reduction_pct within twelve-decimal rounding.
Integration use cases
Health-app and EHR unit tests
Generate known-good recovery fixtures plus deliberate negative years-smoked rejections for cessation-tracker expected values and validator suites.
Technical questions
Why do I have to send a reference date as well as the quit date?
Time since quit is a calendar difference. Supplying as_of keeps the result deterministic without the server clock, so the browser widget and the API always agree for the same dates.