WildfireWindow

How we calculate AQI

Last reviewed 2026-07-15. This is the page we point skeptics to.

The 2024 EPA standard (this is the #1 accuracy trap)

On May 6, 2024 the EPA revised the PM2.5 AQI breakpoints alongside the new annual PM2.5 standard. The old table (where 0–12.0 µg/m³ was "Good") is still everywhere online — and it is now wrong. Under the current table, a 24-hour PM2.5 of 12.0 µg/m³ is AQI 56 ("Moderate"), not 50. We use only the 2024 table.

AQICategoryWhat it means
0–50GoodAir quality is satisfactory, and air pollution poses little or no risk.
51–100ModerateAir quality is acceptable. There may be a risk for people who are unusually sensitive to particle pollution.
101–150Unhealthy for Sensitive GroupsMembers of sensitive groups (people with heart or lung disease, older adults, children and teens, and pregnant people) may experience health effects. The general public is less likely to be affected.
151–200UnhealthySome members of the general public may experience health effects; members of sensitive groups may experience more serious effects.
201–300Very UnhealthyHealth alert: the risk of health effects is increased for everyone.
301–500HazardousHealth warning of emergency conditions: everyone is more likely to be affected.

NowCast — what "current AQI" actually means

A single raw hourly reading, or a flat 24-hour average, both disagree with AirNow when smoke moves fast. EPA's NowCast weights the last 12 hours so recent hours count more when conditions change quickly. We implement it exactly, and it's why our "now" number tracks AirNow instead of lagging or spiking.

AirNow is our display truth

For any US location the AQI and category we show come from AirNow — the EPA/NOAA system that computes the official number. We never display a self-computed AQI that disagrees with AirNow for the same monitor. Our own engine fills the gaps AirNow doesn't hand us pre-computed (raw sensor concentrations, NowCast, forecasts, history).

Provenance on every reading

Every number shows its source (AirNow / OpenAQ / forecast), the reporting area or monitor, the observation time, and "updated X min ago." A reading older than 90 minutes renders in a visibly degraded "last known" state — we never make stale data look fresh.

Validation

A test harness (npm run validate:aqi) gates every deploy. It checks the 2024-table trap vectors, a NowCast worked example, and a live diff against AirNow reporting areas. If our derivation disagrees with AirNow, the build fails.

Data sources & update cadence

Full attribution Embed our live badge