Type 2 diabetes risk score
A 52-year-old man with a BMI of 28.4, a 96 cm waist, little daily exercise, no daily vegetables, blood pressure pills and a parent with diabetes scores 16 FINDRISC points: high risk, about 33 % over ten years. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Age
- 52
- Bmi
- 28.4
- Waist
- 96
- Sex
- Male
- Activity
- less_than_30min
- Diet
- Not daily
- Points
- 16
- Risk category
- high
- Risk category label
- High
- Estimated 10y risk percent
- 33
Type 2 diabetes often develops silently, and a structured screening score lets people, coaches, and product teams rank relative risk from everyday measurements instead of waiting for a laboratory diagnosis. This capability implements the Finnish Diabetes Risk Score (FINDRISC): it converts age, body-mass index, waist circumference, sex-specific waist bands, daily physical activity, vegetable and fruit intake, antihypertensive treatment, prior high blood glucose, and family history of diabetes into integer points and a five-level category from low to very high.
How points add up and how categories are assigned
Each item contributes a published integer; the engine sums them and maps the total onto five categories. Age scores zero under forty-five, two from forty-five through fifty-four, three from fifty-five through sixty-four, and four from sixty-five upward. BMI scores zero below twenty-five, one from twenty-five through thirty, and three above thirty.
Waist uses sex-specific bands: men score zero below ninety-four centimetres, three from ninety-four through one hundred two, and four above that; women score zero below eighty, three from eighty through eighty-eight, and four above eighty-eight. Daily thirty-minute activity scores zero; less than thirty minutes scores two. Daily vegetables score zero; not daily scores one.
Antihypertensive treatment scores two when true. Prior high blood glucose scores five when true. Family history scores zero, three, or five.
The maximum is twenty-six. Totals under seven are low (about one percent ten-year risk in the original table); seven through eleven slightly elevated (about four percent); twelve through fourteen moderate (about seventeen percent); fifteen through twenty high (about thirty-three percent); above twenty very high (about fifty percent).
What you can do with it
Wellness apps and patient-education pages
Health apps collect age, BMI, waist, activity, diet, and history once, then show a FINDRISC category chip without shipping a second copy of the point table on every client.
Occupational-health and clinic intake
Intake forms score adults before a visit so staff can flag high and very high totals for follow-up discussion, while invalid BMI never looks like a successful screen.
FAQ
What scoring system does this type 2 diabetes risk calculator use?
The Finnish Diabetes Risk Score (FINDRISC): integer points from age, BMI, sex-specific waist circumference, daily activity, vegetable intake, antihypertensive treatment, prior high blood glucose, and family history, mapped to low, slightly elevated, moderate, high, and very high.
What happens if BMI is zero, negative, or not a number?
BMI must be a positive number (body-mass index in kg/m²); missing, non-finite, zero, and negative values are rejected and are not charged.
Why is sex required if BMI is already provided?
FINDRISC waist cut-offs differ for men and women. Sex selects that table; BMI uses a single unisex band. Without sex the waist item cannot be scored.
Is a FINDRISC category a diagnosis of type 2 diabetes?
No. It is an educational screening score with published ten-year risk bands. It does not replace glucose testing, HbA1c, or professional medical advice.
Is the type 2 diabetes risk score free?
The browser tool runs free on your device.
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/risk-dm \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"age":52,"bmi":28.4,"waist":96,"sex":"male","activity":"less_than_30min","diet":"not_daily","hypertension_treatment":true,"high_blood_glucose":false,"family_history":"first_degree"}'const res = await fetch("https://api.kit.forhosting.com/health/risk-dm", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"age": 52,
"bmi": 28.4,
"waist": 96,
"sex": "male",
"activity": "less_than_30min",
"diet": "not_daily",
"hypertension_treatment": true,
"high_blood_glucose": false,
"family_history": "first_degree"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/health/risk-dm",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"age": 52,
"bmi": 28.4,
"waist": 96,
"sex": "male",
"activity": "less_than_30min",
"diet": "not_daily",
"hypertension_treatment": true,
"high_blood_glucose": false,
"family_history": "first_degree"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/health/risk-dm", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"age":52,"bmi":28.4,"waist":96,"sex":"male","activity":"less_than_30min","diet":"not_daily","hypertension_treatment":true,"high_blood_glucose":false,"family_history":"first_degree"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"age":52,"bmi":28.4,"waist":96,"sex":"male","activity":"less_than_30min","diet":"not_daily","hypertension_treatment":true,"high_blood_glucose":false,"family_history":"first_degree"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/health/risk-dm", 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": 52,
"bmi": 28.4,
"waist": 96,
"sex": "male",
"activity": "less_than_30min",
"diet": "not_daily",
"hypertension_treatment": true,
"high_blood_glucose": false,
"family_history": "first_degree"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "health.risk_dm",
"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 comparison and addition with no network, no model, and no wall clock, so homework checkers, wellness apps, and prepaid API clients pin identical JSON. BMI must be a positive number; missing, non-finite, zero, or negative BMI fails with invalid_input and is not charged.
What FINDRISC measures and which inputs you send
FINDRISC is a published adult screening questionnaire that estimates ten-year type 2 diabetes risk from lifestyle and history items a clinic or app can collect without a blood draw. Send required age in years (adults eighteen to one hundred twenty), bmi as a positive body-mass index in kilograms per square metre, waist circumference in centimetres, and sex so the waist cut-offs can use the male or female table. The score is educational screening, not a diagnosis, a glucose lab, or an HbA1c substitute, and it is not validated here as a pediatric tool. Activity is the closed set daily_30min or less_than_30min for usual thirty-minute daily movement at work or leisure. Diet is daily_vegetables or not_daily for vegetables, fruit, or berries. Medical history is three fields: hypertension_treatment (boolean, regular antihypertensive medication ever), high_blood_glucose (boolean, glucose ever found high in a check, illness, or pregnancy), and family_history as none, second_degree (grandparent, aunt, uncle, or first cousin only), or first_degree (parent, sibling, or own child). Aliases exist for each canonical name so older forms can map without renaming columns. Missing fields, non-finite numbers, out-of-range age, unknown enums, and any BMI that is not a positive number fail with invalid_input naming the field.
How points add up and how categories are assigned
The response echoes the inputs, returns points as the integer total, breakdown as per-item points, risk_category as a stable machine key, risk_category_label for display, estimated_10y_risk_percent from that table, score_max twenty-six, method findrisc, and score_name FINDRISC. Identical inputs always yield identical JSON.
API usage, pricing, product workflows, and honest limits
Call the free in-browser type 2 diabetes risk score for classroom demos, occupational-health kiosks, and personal education pages without re-coding FINDRISC bands in every spreadsheet. Keep expectations educational: a screening score is not a medical device diagnosis, does not replace fasting glucose or HbA1c, and people with symptoms, pregnancy, or known diabetes should follow professional medical advice rather than any single automated label. POST a JSON body with the nine required fields and read points plus risk_category as the primary contract. Use the prepaid API when a wellness app, telehealth intake, research eCRF, or school LMS needs a stable contract under KIT balance at $0.002 per successful item; validation failures never consume balance after the engine rejects the request. Store the integer total alongside the category key so dashboards can filter high and very_high rows without parsing labels, and keep breakdown when you want to show which items drove the score. Prefer centimetres for waist and kilograms per square metre for BMI; if your UI collects height and weight, compute BMI upstream and send the positive index this endpoint requires.
Integration use cases
Public-health homework and LMS checkers
Students submit questionnaire answers and pin expected points and risk_category JSON; the deterministic parse path marks the same total every time.