SIR epidemic calculator
With 990 susceptible and 10 infected people, an infection rate of 0.3 and a recovery rate of 0.1, the basic reproduction number is 3 and about 24 people are infected by day 5. Get the full daily S, I and R table. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Infection rate
- 0.3
- Recovery rate
- 0.1
- Susceptible
- 990
- Infected
- 10
- Recovered
- 0
- Days
- 5
- Population
- 1,000
- Peak infected
- 24.35274342
- Peak day
- 5
- Final susceptible
- 968.26496445
The classic SIR epidemic model splits a closed population into three compartments: people who are still susceptible to infection, people who are currently infectious, and people who have recovered and are treated as immune for the rest of the run. This viral infection SIR calculator steps that model forward one day at a time from an infection rate, a recovery rate, the three starting compartment sizes, and a horizon in days. Each day new infections move from susceptible into infected in proportion to both groups, and recoveries move from infected into recovered at the recovery rate. The response is a day-by-day table of susceptible, infected, and recovered counts together with the implied basic reproduction number and the peak of the infected curve. Negative infection or recovery rates are rejected as invalid input rather than being folded into absolute values.
How the SIR epidemic model is defined
The susceptible-infected-recovered model is the smallest closed-population epidemic that still shows a rise-and-fall infected curve. Everyone starts in one of three stocks: susceptible people who can catch the pathogen, infected people who can transmit it, and recovered people who are treated as immune for the rest of this run. There are no births, deaths, or migrations, so the total N equals S plus I plus R stays constant and is only a scale for contact.
Each day the calculator applies one Euler step of the Kermack–McKendrick equations with a unit time step of one day: new infections equal the infection rate beta times S times I divided by N, and new recoveries equal the recovery rate gamma times I. Those flows leave S, enter I, then leave I into R. When gamma is positive, the basic reproduction number R0 equals beta divided by gamma, the number of secondary cases one infectious person would produce in a fully susceptible population.
A value above one is the classic condition for an epidemic takeoff, and the educational herd-immunity threshold one minus one over R0 is reported only in that case. The implementation is the textbook daily Euler method, not an adaptive ordinary-differential-equation solver, not a stochastic agent model, and not a forecast of a named real-world outbreak. Large rates are clamped so a single step cannot drive a compartment negative, because a negative head-count is not a valid stock.
Fractional compartment values are allowed: the continuous approximation is not restricted to whole people. Treat every series as an educational trajectory from this published rule, never as a clinical prediction, a hospital-bed forecast, or a substitute for a structured public-health model with age, behaviour, or vaccination layers this tool does not collect.
Where SIR calculators show up in real work
Epidemiology courses, nursing orientation, and public-health workshops constantly assign SIR drills from textbook rates and starting stocks, so a single trusted oracle that returns the daily table beside R0 and the infected peak speeds grading and demo setup. Simulation centres and electronic worksheet products want a documented beta, gamma, S, I, R, and days path that clients can audit by hand rather than a black-box neural forecast that mixes mobility, weather, and behaviour without disclosure.
Research assistants preparing synthetic outbreak datasets need stable compartment labels from known rates without network calls or model drift, and they need a hard reject when a rate arrives negative so dirty extracts cannot masquerade as trajectories. If you later need SEIR with an exposed class, vital dynamics, age structure, vaccination campaigns, or a stochastic agent model, treat those as separate search intents and landings rather than overloading this viral infection SIR page.
Always present results as educational estimates from the published daily Euler rule; operational decisions require qualified professionals, local surveillance, and models that this tool does not claim to replace. Keep requests inside the three-hundred-sixty-five-day cap, pin the series in tests, and you get reproducible SIR figures for homework, LMS plugins, and edge workers without standing up an outbreak-modelling stack of your own.
What you can do with it
Classroom SIR answer keys
Generate the daily susceptible, infected, and recovered table plus R0 from textbook beta, gamma, and starting stocks so instructors and auto-graders share one transparent ground truth.
Epidemiology-lab outbreak drills
Show a closed-population SIR takeoff and fade in teaching labs without mixing SEIR, age structure, or stochastic agents on the same landing.
FAQ
What is the SIR epidemic model?
SIR splits a closed population into susceptible, infected, and recovered compartments. New infections move from S to I in proportion to both groups; recoveries move from I to R. The total N = S + I + R stays constant. This calculator reports the daily counts of those three stocks.
What formula do you use each day?
A daily Euler step of the Kermack–McKendrick equations: new infections = β S I / N, new recoveries = γ I, then S' = S − new infections, I' = I + new infections − new recoveries, R' = R + new recoveries. Time step is one day. When γ > 0, R0 = β / γ.
What happens if an infection or recovery rate is negative?
A negative per-day rate is rejected rather than being converted to an absolute value or a silent NaN.
What does it cost?
The browser tool is free and runs locally.
What does a basic reproduction number of 3 mean in the SIR model?
It is the infection rate divided by the recovery rate, so 0.3 over 0.1 gives 3: one infectious person would infect three others in a fully susceptible population. Above one the epidemic takes off, and only then is the herd-immunity threshold reported.
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/viral-infection-sir \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"infection_rate":0.3,"recovery_rate":0.1,"susceptible":990,"infected":10,"recovered":0,"days":5}'const res = await fetch("https://api.kit.forhosting.com/health/viral-infection-sir", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"infection_rate": 0.3,
"recovery_rate": 0.1,
"susceptible": 990,
"infected": 10,
"recovered": 0,
"days": 5
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/health/viral-infection-sir",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"infection_rate": 0.3,
"recovery_rate": 0.1,
"susceptible": 990,
"infected": 10,
"recovered": 0,
"days": 5
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/health/viral-infection-sir", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"infection_rate":0.3,"recovery_rate":0.1,"susceptible":990,"infected":10,"recovered":0,"days":5}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"infection_rate":0.3,"recovery_rate":0.1,"susceptible":990,"infected":10,"recovered":0,"days":5}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/health/viral-infection-sir", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"infection_rate": 0.3,
"recovery_rate": 0.1,
"susceptible": 990,
"infected": 10,
"recovered": 0,
"days": 5
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "health.viral_infection_sir",
"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_days | 365 |
max_population | 1000000000000 |
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
Successful API calls use the published $0.002 per item; invalid input is not billed.
What you send and what you get back
Send six required fields. The fields susceptible, infected, and recovered are the day-zero compartment counts and must be finite and non-negative; their sum N must be greater than zero so the contact term is defined. The field days is the integer horizon from one through three hundred sixty-five; the series includes day zero through that day. Optional keys are omitted rather than set to null. Pin the series and the peak in tests so a later change to the Euler step cannot pass unnoticed. The field infection_rate is the per-day infection parameter beta and must be a finite non-negative number; a negative value fails with invalid_input naming that field. Aliases beta, beta_rate, transmission_rate, and infectivity are accepted. The field recovery_rate is the per-day recovery parameter gamma and must be a finite non-negative number; aliases gamma, gamma_rate, and recover_rate are accepted. Aliases s, s0, i, i0, rec, initial_susceptible, initial_infected, and initial_recovered are accepted. Missing required fields, empty strings, non-numeric text, NaN, Infinity, a non-integer horizon, and a zero total population fail with invalid_input and are not charged. On success the response echoes the cleaned rates, initial compartments, days, and population, returns series as an array of day, susceptible, infected, and recovered records, reports peak_infected and peak_day, reports final_susceptible, final_infected, and final_recovered, and includes formula and method strings for display and for pinning in tests. When recovery_rate is positive the response also includes r0 equal to beta over gamma, and when r0 is greater than one it includes herd_immunity_threshold. Pricing for successful API calls is the published $0.002 per item; validation failures do not consume prepaid balance.
Where SIR calculators show up in real work
Because this capability is a pure parse engine, API pricing is the published base of $0.002 per successful item and failed validation does not consume balance.
Integration use cases
Deterministic outbreak fixtures
Bulk-produce stable SIR series for synthetic epidemic datasets and regression tests, with hard invalid_input on a negative infection or recovery rate.
Technical questions
How do I format the input?
Send infection_rate and recovery_rate as finite non-negative numbers (for example 0.3 and 0.1), susceptible, infected, and recovered as finite non-negative counts (for example 990, 10, and 0), and days as an integer from 1 to 365. Aliases beta, gamma, s, i, and rec are also accepted.