Air Quality Index (AQI) Calculator
The Air Quality Index (AQI) is a tool used to communicate how clean or polluted the air currently is, or how clean it is forecast to become. It focuses on health effects you may experience within a few hours or days after breathing polluted air. The EPA calculates the AQI for five major air pollutants regulated by the Clean Air Act: ground-level ozone, particle pollution (also known as particulate matter, including PM2.5 and PM10), carbon monoxide, sulfur dioxide, and nitrogen dioxide.
A higher AQI value indicates a greater level of air pollution and a greater health concern. For example, an AQI value of 50 or below represents good air quality, while an AQI value over 300 represents hazardous air quality.
This calculator provides a simplified AQI estimation based on common pollutants like PM2.5 and Ozone, using standard breakpoints. The overall AQI is determined by the pollutant with the highest individual AQI value.
AQI Categories and Health Implications:
0-50: Good – Air quality is considered satisfactory, and air pollution poses little or no risk.
51-100: Moderate – Air quality is acceptable; however, for some pollutants there may be a moderate health concern for a very small number of people who are unusually sensitive to air pollution.
101-150: Unhealthy for Sensitive Groups – Members of sensitive groups may experience health effects. The general public is less likely to be affected.
151-200: Unhealthy – Everyone may begin to experience health effects; members of sensitive groups may experience more serious health effects.
201-300: Very Unhealthy – Health warnings of emergency conditions. The entire population is more likely to be affected.
301-500: Hazardous – Health alert: everyone may experience more serious health effects.
Calculate Your Estimated AQI
PM2.5 Concentration (µg/m³):
Ozone (O3) Concentration (ppb, 8-hour average):
Calculate AQI
How AQI is Calculated (Simplified)
The AQI is calculated using a linear interpolation formula for each pollutant. The formula is:
I = [(Ihi - Ilo) / (Chi - Clo)] * (Cp - Clo) + Ilo
I = the AQI value
Cp = the pollutant concentration
Ihi = the AQI value corresponding to Chi
Ilo = the AQI value corresponding to Clo
Chi = the breakpoint concentration that is greater than or equal to Cp
Clo = the breakpoint concentration that is less than or equal to Cp
The overall AQI is the highest individual AQI calculated among all pollutants. This calculator uses the following simplified breakpoints:
PM2.5 (24-hour average, µg/m³) Breakpoints:
Concentration (µg/m³) AQI Category
0.0 – 12.0 0-50 Good
12.1 – 35.4 51-100 Moderate
35.5 – 55.4 101-150 Unhealthy for Sensitive Groups
55.5 – 150.4 151-200 Unhealthy
150.5 – 250.4 201-300 Very Unhealthy
250.5 – 500.4 301-500 Hazardous
Ozone (O3, 8-hour average, ppb) Breakpoints:
Concentration (ppb) AQI Category
0 – 54 0-50 Good
55 – 70 51-100 Moderate
71 – 85 101-150 Unhealthy for Sensitive Groups
86 – 105 151-200 Unhealthy
106 – 200 201-300 Very Unhealthy
Example Calculation:
Let's say the PM2.5 concentration is 45.0 µg/m³ and Ozone concentration is 75 ppb .
For PM2.5 (45.0 µg/m³): This falls into the "Unhealthy for Sensitive Groups" category (35.5-55.4 µg/m³, AQI 101-150).
Cp = 45.0
Clo = 35.5, Ilo = 101
Chi = 55.4, Ihi = 150
AQI_PM2.5 = [(150 – 101) / (55.4 – 35.5)] * (45.0 – 35.5) + 101
AQI_PM2.5 = [49 / 19.9] * 9.5 + 101 ≈ 2.462 * 9.5 + 101 ≈ 23.399 + 101 ≈ 124.4
For Ozone (75 ppb): This falls into the "Unhealthy for Sensitive Groups" category (71-85 ppb, AQI 101-150).
Cp = 75
Clo = 71, Ilo = 101
Chi = 85, Ihi = 150
AQI_Ozone = [(150 – 101) / (85 – 71)] * (75 – 71) + 101
AQI_Ozone = [49 / 14] * 4 + 101 = 3.5 * 4 + 101 = 14 + 101 = 115
The maximum AQI is 124.4 (from PM2.5). Therefore, the overall AQI is 124 , which is "Unhealthy for Sensitive Groups".
.calculator-container {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f9f9f9;
padding: 25px;
border-radius: 10px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
max-width: 800px;
margin: 20px auto;
color: #333;
line-height: 1.6;
}
.calculator-container h2, .calculator-container h3 {
color: #2c3e50;
text-align: center;
margin-bottom: 20px;
}
.calculator-container p {
margin-bottom: 15px;
text-align: justify;
}
.form-group {
margin-bottom: 15px;
display: flex;
flex-direction: column;
}
.form-group label {
margin-bottom: 8px;
font-weight: bold;
color: #555;
}
.form-group input[type="number"] {
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 16px;
width: 100%;
box-sizing: border-box;
}
.calculate-button {
background-color: #3498db;
color: white;
padding: 12px 25px;
border: none;
border-radius: 5px;
font-size: 18px;
cursor: pointer;
transition: background-color 0.3s ease;
width: 100%;
box-sizing: border-box;
margin-top: 10px;
}
.calculate-button:hover {
background-color: #2980b9;
}
.result-container {
margin-top: 25px;
padding: 20px;
border: 1px solid #eee;
border-radius: 8px;
background-color: #eaf4f9;
min-height: 50px;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
font-size: 1.1em;
font-weight: bold;
color: #2c3e50;
}
.result-container.good { background-color: #d4edda; color: #155724; border-color: #c3e6cb; }
.result-container.moderate { background-color: #fff3cd; color: #856404; border-color: #ffeeba; }
.result-container.sensitive { background-color: #f8d7da; color: #721c24; border-color: #f5c6cb; } /* Unhealthy for Sensitive Groups */
.result-container.unhealthy { background-color: #f8d7da; color: #721c24; border-color: #f5c6cb; }
.result-container.very-unhealthy { background-color: #f0e0f7; color: #6f42c1; border-color: #e0cff7; }
.result-container.hazardous { background-color: #f5c6cb; color: #721c24; border-color: #f1b0b7; }
.calculator-container table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
margin-bottom: 20px;
}
.calculator-container th, .calculator-container td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
.calculator-container th {
background-color: #f2f2f2;
font-weight: bold;
color: #555;
}
.calculator-container ul {
list-style-type: disc;
margin-left: 20px;
margin-bottom: 15px;
}
.calculator-container ul li {
margin-bottom: 5px;
}
function calculateAQI() {
var pm25Concentration = parseFloat(document.getElementById('pm25Concentration').value);
var ozoneConcentration = parseFloat(document.getElementById('ozoneConcentration').value);
var resultDiv = document.getElementById('aqiResult');
if (isNaN(pm25Concentration) || pm25Concentration < 0) {
resultDiv.innerHTML = "Please enter a valid PM2.5 concentration.";
resultDiv.className = 'result-container';
return;
}
if (isNaN(ozoneConcentration) || ozoneConcentration < 0) {
resultDiv.innerHTML = "Please enter a valid Ozone concentration.";
resultDiv.className = 'result-container';
return;
}
var aqiPM25 = calculatePollutantAQI(pm25Concentration, 'pm25');
var aqiOzone = calculatePollutantAQI(ozoneConcentration, 'ozone');
var overallAQI = Math.round(Math.max(aqiPM25, aqiOzone));
var category = getAQICategory(overallAQI);
var healthMessage = getHealthMessage(overallAQI);
var categoryClass = getCategoryClass(overallAQI);
resultDiv.innerHTML = "Your Estimated AQI:
" + overallAQI + " (" + category + ")" + healthMessage;
resultDiv.className = 'result-container ' + categoryClass;
}
function calculatePollutantAQI(concentration, pollutantType) {
var breakpoints;
if (pollutantType === 'pm25') {
// PM2.5 (24-hour average, µg/m³) breakpoints
breakpoints = [
{ C_lo: 0.0, C_hi: 12.0, I_lo: 0, I_hi: 50 },
{ C_lo: 12.1, C_hi: 35.4, I_lo: 51, I_hi: 100 },
{ C_lo: 35.5, C_hi: 55.4, I_lo: 101, I_hi: 150 },
{ C_lo: 55.5, C_hi: 150.4, I_lo: 151, I_hi: 200 },
{ C_lo: 150.5, C_hi: 250.4, I_lo: 201, I_hi: 300 },
{ C_lo: 250.5, C_hi: 500.4, I_lo: 301, I_hi: 500 }
];
} else if (pollutantType === 'ozone') {
// Ozone (8-hour average, ppb) breakpoints
breakpoints = [
{ C_lo: 0, C_hi: 54, I_lo: 0, I_hi: 50 },
{ C_lo: 55, C_hi: 70, I_lo: 51, I_hi: 100 },
{ C_lo: 71, C_hi: 85, I_lo: 101, I_hi: 150 },
{ C_lo: 86, C_hi: 105, I_lo: 151, I_hi: 200 },
{ C_lo: 106, C_hi: 200, I_lo: 201, I_hi: 300 }
// Note: Ozone > 200 ppb is hazardous, but EPA table typically caps at 200 for 8-hr.
// For simplicity, we'll cap at 300 AQI for this range.
];
} else {
return 0; // Should not happen
}
// Handle concentrations outside the defined ranges
if (concentration breakpoints[breakpoints.length – 1].C_hi) {
// For values above the highest breakpoint, assume it continues in the highest category
var lastBp = breakpoints[breakpoints.length – 1];
// Simple extrapolation or cap at max AQI for the highest category
// For simplicity, we'll cap at the highest AQI in the table for now.
// A more precise calculation would extrapolate or use a fixed max.
return lastBp.I_hi;
}
for (var i = 0; i = bp.C_lo && concentration = 0 && aqi = 51 && aqi = 101 && aqi = 151 && aqi = 201 && aqi = 301) return "Hazardous";
return "N/A";
}
function getHealthMessage(aqi) {
if (aqi >= 0 && aqi = 51 && aqi = 101 && aqi = 151 && aqi = 201 && aqi = 301) return "Health alert: everyone may experience more serious health effects.";
return "Unable to determine health message.";
}
function getCategoryClass(aqi) {
if (aqi >= 0 && aqi = 51 && aqi = 101 && aqi = 151 && aqi = 201 && aqi = 301) return "hazardous";
return "";
}