PSI calculator
A 65-year-old man with heart failure, a breathing rate of 32 and a blood urea of 35 mg/dL scores 115 points: risk class IV, with about 9.3% 30-day mortality. Enter age, sex, conditions, vital signs and lab results to get the class. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Runs in your browser. Free, unlimited — your data never leaves this page.
The Pneumonia Severity Index, also published as the PORT score after the Pneumonia Patient Outcomes Research Team, is a widely taught additive rule for community-acquired pneumonia. This calculator implements the Fine 1997 two-step algorithm: it converts demographics, five comorbidity flags, vital-sign thresholds, and laboratory cutoffs into a point total, then assigns risk class I through V with a published 30-day mortality band and a disposition hint. Optional flags and labs that you omit contribute zero points, which means they are treated as not meeting that criterion.
What the Pneumonia Severity Index measures and how Fine’s two steps work
Community-acquired pneumonia covers a wide range of 30-day risk, from previously healthy adults who recover at home to patients who need inpatient monitoring. Fine and colleagues derived the Pneumonia Severity Index from the PORT cohort and published the rule in the New England Journal of Medicine in 1997 so that clinicians and students could stratify that range with a single, inspectable score instead of an opaque model.
Step 1 asks whether the patient is fifty years of age or younger and has none of five comorbidities—neoplastic disease, liver disease, congestive heart failure, cerebrovascular disease, and renal disease—and none of five examination findings: altered mental status, respiratory rate at least thirty breaths per minute, systolic blood pressure below ninety millimetres of mercury, temperature below thirty-five or at least forty degrees Celsius, and pulse at least one hundred twenty-five beats per minute.
When every Step 1 screen is negative, the original algorithm assigns risk class I without waiting for laboratory points. Step 2 always still computes an additive total: men receive their age in years as demographic points and women receive age minus ten; a nursing-home resident adds ten; comorbidities add thirty, twenty, or ten according to the published table; examination abnormalities add twenty, fifteen, or ten; and laboratory or radiographic findings add thirty for acidemia, twenty for elevated urea or hyponatremia, and ten for hyperglycemia, anemia, hypoxemia, or pleural effusion.
Classes II through V then follow the cutoffs at seventy, ninety, and one hundred thirty points.
Input contract, units, validation, and the shape of a successful response
Sex must be male or female (single-letter m or f is normalized) because the Fine table subtracts ten points for women. Every comorbidity and the nursing-home and pleural-effusion flags are optional booleans that default to false.
Vital signs and laboratories are optional finite numbers: respiratory rate in breaths per minute, systolic blood pressure in millimetres of mercury, temperature in Celsius, pulse in beats per minute, arterial pH, blood urea nitrogen in milligrams per decilitre, sodium in milliequivalents per litre, glucose in milligrams per decilitre, hematocrit in percent, arterial oxygen tension in millimetres of mercury, and oxygen saturation in percent. An omitted vital or lab contributes zero points rather than inventing a normal value, so a score computed from demographics alone is honest about what was scored.
Hypoxemia is awarded at most ten points if either PaO2 is below sixty or saturation is below ninety, never twenty for sending both. Optional output keys are omitted rather than set to null.
How to read risk classes, where the calculator belongs, and what it does not decide
Risk class I is very low risk, with a PORT validation mortality near one tenth of a percent, and the usual teaching disposition is outpatient care when the social setting is safe. Class II remains low risk at about six tenths of a percent and is also commonly taught as outpatient. Class III is moderate risk near nine tenths of a percent and is often framed as observation or a short inpatient stay.
Class IV is high risk near nine point three percent and class V is very high risk near twenty-seven percent; both are taught as inpatient strata, with class V prompting a conversation about higher-acuity monitoring. Those percentages are historical cohort figures from the original validation, not a personal prognosis, and they do not replace CURB-65, ATS/IDSA major-minor criteria, oxygenation trends, or a clinician’s view of comorbidities this table never captures.
Because Step 1 ignores laboratories, a young adult who meets class I screens can still carry lab points in the numeric score; the response reports both the class and the buckets so you can see that tension instead of hiding it. Use the calculator for education, exam keys, research coding of community-acquired pneumonia rows, and product prototypes that need a deterministic PSI step before handing off to licensed systems.
Neighbouring tools such as CURB-65, shock index, or eGFR answer different search intents and should keep their own landings rather than being overloaded here.
What you can do with it
Teaching vignettes and exam keys
Score textbook community-acquired pneumonia cases so instructors and auto-graders share one Fine 1997 ground truth for points and risk class.
Research coding of pneumonia cohorts
Attach a reproducible PSI total and class I–V label to study rows when demographics, flags, vitals, and selected labs are already in the table.
Prototype decision-support scaffolds
Wire a transparent Pneumonia Severity Index step into educational apps and checklists that later hand off to licensed clinical systems for real decisions.
FAQ
What is the Pneumonia Severity Index (PSI / PORT score)?
It is Fine’s 1997 additive rule for community-acquired pneumonia. This tool returns the point total, risk class I–V, a short label, a PORT validation mortality percentage, and a teaching disposition hint.
How is the PSI score calculated from the inputs?
Men receive their age as points and women receive age minus 10. Nursing-home residence, five comorbidities, five exam thresholds, and selected lab or radiographic cutoffs add the published Fine weights. Class I is assigned in Step 1 when age is 50 or under and those comorbidity and exam screens are all negative.
How should I interpret risk classes I through V?
Classes I and II are taught as very low and low risk (often outpatient). Class III is moderate risk (observation or a short stay). Classes IV and V are high and very high risk (inpatient teaching strata). Figures are historical cohort rates, not a personal prognosis.
Can I use this result to decide admission or treatment?
No. This is an educational arithmetic aid, not medical advice. Admission, antibiotics, and intensity of care need a licensed clinician and the rest of the clinical picture this calculator does not collect.
What if I do not have every lab result?
Any condition, vital sign or lab you leave out adds zero points, as if it did not meet that criterion. Only age and sex are needed, but a missing abnormal result is simply not counted in the total.
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/psi \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"age":65,"sex":"male"}'const res = await fetch("https://api.kit.forhosting.com/health/psi", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"age": 65,
"sex": "male"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/health/psi",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"age": 65,
"sex": "male"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/health/psi", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"age":65,"sex":"male"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"age":65,"sex":"male"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/health/psi", 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": 65,
"sex": "male"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "health.psi",
"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
Age must be a finite positive number; a missing, zero, negative, or non-numeric age fails with invalid_input and is not billed. Treat the JSON as a transparent arithmetic aid, not a diagnosis or a substitute for licensed clinical judgment.
What the Pneumonia Severity Index measures and how Fine’s two steps work
This capability implements that published table exactly, with no hidden weights, so a hand-scored vignette and the JSON body can be compared line by line.
Input contract, units, validation, and the shape of a successful response
Zero, negative values, empty strings, and non-numeric tokens fail with invalid_input naming age, matching the classroom rule that a Pneumonia Severity Index is undefined without a positive age in years. On success the body returns score, risk_class as a Roman numeral I through V, a short risk_class_label, mortality_pct from the PORT validation band, a disposition string, echoed age and sex, the point buckets age_points, nursing_home_points, comorbidity_points, exam_points, and lab_points, a class_i_eligible flag for Step 1, and formula PSI/PORT Fine 1997. Pair the free browser form with the same contract from scripts; successful API calls cost $0.002 per item and validation failures do not consume prepaid balance.
How to read risk classes, where the calculator belongs, and what it does not decide
Do not dose antibiotics, refuse admission, or discharge a patient from this JSON alone. The arithmetic is pure parse with no outbound network, so identical inputs always yield identical JSON, and the published API price remains $0.002 per successful request.
Technical questions
What happens if age is zero, negative, or missing?
The call fails with invalid_input. Age must be a finite positive number; without it the Pneumonia Severity Index is not defined and the request is not billed.
What does the PSI calculator cost?
The browser widget runs free and locally. The same computation via the API is billed at $0.002 per successful request from prepaid KIT balance; invalid_input failures are not charged.