airq
Check air quality from your terminal. Any city in the world, no API key needed. Detects pollution fronts, generates visual reports with maps and heatmaps.

Pollution front analysis for Hamburg — 522 sensors, cross-correlation tracking, heatmap overlay. Generated with airq report --city hamburg --radius 150 --pdf
By default merges two data sources for more accurate results:
- Open-Meteo — global model (PM2.5, PM10, CO, NO2, O3, SO2, UV)
- Sensor.Community — citizen science sensors (15,000+ real sensors worldwide)
Install
Or download prebuilt binaries from GitHub Releases.
Quick start
Resolved city: Gazipaşa, Türkiye
Sources: Open-Meteo (model) + Sensor.Community (1 sensors, 5km median)
--------------------------------------------------
PM2.5 9.6 avg (12.7 model, 6.5 sensors) μg/m³
PM10 14.7 avg (16.2 model, 13.1 sensors) μg/m³
CO 159.0 μg/m³
NO2 1.9 μg/m³
O3 73.0 μg/m³
SO2 1.1 μg/m³
UV Index: 0 ☀️ (Low)
Wind: 5.2 km/h ↙ NE (gusts 8)
--------------------------------------------------
🟢 US AQI: 40 | EU AQI: 29 — Good
Commands
Any city in the world
By coordinates
History (sparkline)
Istanbul, Türkiye — last 5 days
2026-03-09: ██░░░ 10.9 µg/m³ (AQI 44 🟢)
2026-03-10: ███░░ 20.7 µg/m³ (AQI 57 🟡)
2026-03-11: ███░░ 21.5 µg/m³ (AQI 68 🟡)
2026-03-12: ███░░ 17.3 µg/m³ (AQI 68 🟡)
2026-03-13: ███░░ 20.3 µg/m³ (AQI 64 🟡)
Top cities by AQI
# City AQI PM2.5
1 Delhi 210 🟣 58.9
2 Mumbai 87 🟡 29.3
3 Bangalore 62 🟡 17.5
4 Chennai 54 🟡 13.7
5 Kolkata 43 🟢 10.2
Any country in the world — 10,000+ cities built-in. Use airq top --country x --list to see all.
Compare providers
Berlin, Germany — Provider Comparison
Sensor.Community: 143 sensors, 5km radius
┌──────────┬───────────┬─────────────────┬─────────┐
│ Metric │ Open-Meteo│ Area Median │ Average │
├──────────┼───────────┼─────────────────┼─────────┤
│ PM2.5 │ 4.2 │ 6.8 │ 5.5 │
│ PM10 │ 5.3 │ 11.1 │ 8.2 │
│ US AQI │ 31 │ 28 (calc) │ 29 │
└──────────┴───────────┴─────────────────┴─────────┘
Single provider
JSON output
All commands support --json:
Pollution front detection
Detect pollution fronts moving between cities using cross-correlation analysis:
Analyzing pollution fronts around Gazipaşa, Türkiye...
Nearby cities (150km radius):
Alanya (42km NW), Manavgat (97km NW), Karaman (129km NE)...
Current wind: 5.2 km/h ↙ NE
Spike detection (last 72h):
🟡 Alanya: 16.8 µg/m³ (+2.6) 2026-03-15 20:00
🟢 Manavgat: 12.0 µg/m³ (+2.0) 2026-03-15 20:00
Pollution fronts detected:
↘ Manavgat → Gazipaşa | 5 km/h SE | lag 20h | corr 87%
⚠ Manavgat → Gazipaşa front detected (lag 20h, 5 km/h)
Uses Z-score spike detection, cross-correlation with time-lag, and haversine geometry to track pollution movement.
HTML report with map
Generate a visual report with Leaflet.js map showing cities, front arrows, and analysis tables:
Opens in any browser. For PDF export (--pdf) you need one of:
- Google Chrome (recommended) — already installed on most systems, used in headless mode
- wkhtmltopdf — lightweight alternative:
Pollution source attribution (blame)
Identify which factories, power plants, or highways contribute to local air pollution:
Auto-discovers factories, power plants, and highways from OpenStreetMap. CPF = probability that high PM2.5 occurs when wind blows from that source direction.
Sources auto-discovered from OpenStreetMap (Overpass API). CPF = probability that high PM2.5 occurs when wind blows from that source. You can also add custom sources in config:
[[]]
= "My Local Factory"
= 55.82
= 37.73
= "factory"
The report command includes blame data too — source markers on the map and CPF table in the PDF.
Find nearby sensors
Configuration
Set up a default city and favorites list so you don't have to type --city every time:
Config file: ~/.config/airq/config.toml
= "tokyo"
= ["tokyo", "berlin", "istanbul", "new york"]
With a favorites list, check all cities at once:
# City AQI PM2.5
1 Istanbul 98 🟡 34.6
2 New York 72 🟡 22.0
3 Berlin 31 🟢 4.2
4 Tokyo 35 🟢 8.3
How it works
By default (--provider all), airq fetches both sources in parallel and averages PM2.5/PM10. Each value shows the breakdown:
PM2.5 4.9 avg (4.2 model, 5.7 sensors) μg/m³
- model = Open-Meteo atmospheric reanalysis (global, ~11km grid)
- sensors = median of all Sensor.Community sensors within 5km (filters outliers)
If no sensors nearby, falls back to model only with a note.
AQI scale
| AQI | Category | Color |
|---|---|---|
| 0–50 | Good | 🟢 |
| 51–100 | Moderate | 🟡 |
| 101–150 | Unhealthy for Sensitive Groups | 🟠 |
| 151–200 | Unhealthy | 🔴 |
| 201–300 | Very Unhealthy | 🟣 |
| 301–500 | Hazardous | 🟤 |
US AQI from Open-Meteo API. EU AQI also shown. For sensor-only data, AQI calculated using EPA formula.
Front detection methodology
The front and report commands use cross-correlation analysis to detect pollution movement:
- Spike detection — Z-score on hourly PM2.5 differences. Flags sudden changes (z > 2σ)
- Cross-correlation — compares time-series between city/sensor pairs with lags -24h to +24h. Peak correlation reveals transit time
- Speed & direction — haversine distance / time lag = front speed. Bearing calculated from coordinates
- Dual-source — when both Open-Meteo (model) and Sensor.Community (ground sensors) are available, correlations are weighted and merged. Agreement boosts confidence
- Sensor clustering — nearby sensors (~5km) are grouped into zones for spatial analysis. Reports show individual sensor locations with PM2.5 heatmap overlay
See examples/ for sample reports.
Data sources
- Open-Meteo Air Quality API — free, no key, global atmospheric model
- Open-Meteo Weather API — wind speed, direction, gusts
- Open-Meteo Geocoding API — city → coordinates
- Sensor.Community — citizen science, 15,000+ real SDS011/PM sensors
- Sensor.Community Archive — historical CSV data per sensor (cached locally)
License
MIT