MapEarthSensing · methodology
How this map is built

What is measured, what is modelled, and where the difference matters

EarthSensing puts two very different kinds of data on the same screen. The coloured rasters draped over the planet are measurements: photons counted by a spectrometer in low Earth orbit, once a day, integrated through the whole depth of the atmosphere. The numbers in the readout panel are model output: a chemical-transport forecast of what the air is like at the ground, right now, at a point.

They agree often enough to be useful together and disagree often enough to be interesting. This page is about when to trust which.

Section 01

A column is not a concentration

TROPOMI, the instrument behind the NO₂ layer, does not measure the air you are breathing. It measures how much sunlight, after bouncing off the surface and travelling back up through the atmosphere, has been absorbed at the wavelengths nitrogen dioxide absorbs at. Inverting that gives a vertical column density: the total number of NO₂ molecules in a tube of air one square centimetre in cross-section, running from the ground to the top of the troposphere. The unit is molecules per square centimetre. There is no depth information in it at all.

The readout panel reports something else entirely: a surface mass concentration in micrograms per cubic metre, at roughly the height of your head, for a specific hour. Getting from one to the other requires knowing how the pollutant is distributed vertically — which the satellite cannot see, and which changes with the time of day, the season, the boundary-layer depth and the weather.

Satellite layerReadout panel
QuantityVertical column densitySurface mass concentration
Unitmolecules/cm² (or Dobson units, or unitless AOD)µg/m³
SourceDirect measurement, inverted from a spectrumAssimilating forecast model (CAMS)
TimeOne overpass, 1–3 days agoThe current hour, plus 5 days ahead
Vertical extentWhole column, no depth resolutionLowest model level

A bright plume on the map with a clean number underneath it is usually not a contradiction. Smoke and dust travel at altitude: a column measurement sees them, and the surface field correctly says they have not come down yet. The aerosol-index layer is especially prone to this — it is most sensitive to absorbing particles high in the atmosphere.

Section 02

The instruments, and what the tiles actually are

Five raster products are available on the layer picker. Each comes from a different sensor with a different footprint, a different overpass time and a different failure mode.

LayerInstrument · platformNative resolutionRevisitLag here
NO₂TROPOMI · Sentinel-5P5.5 × 3.5 km at nadirDaily, ~13:30 local overpass2 days
AODMODIS · Terra10 km (Deep Blue L2)Daily, ~10:30 local overpass1 day
AOD·VVIIRS · NOAA-206 km (Deep Blue L2)Daily, ~13:30 local overpass1 day
SmokeOMI · Aura13 × 24 km at nadirDaily, ~13:45 local overpass2 days
SO₂TROPOMI · Sentinel-5P5.5 × 3.5 km at nadirDaily, ~13:30 local overpass2 days
  • NO₂Cloud-screened; a persistently cloudy week leaves holes in the record.
  • AODRetrieval fails over bright cloud and, for the standard algorithm, over bright desert — Deep Blue exists to recover the desert case.
  • AOD·VWider swath than MODIS, so fewer between-orbit gaps at low latitudes.
  • SmokeWorks over cloud and bright surfaces, and responds to absorbing particles aloft — smoke and dust — more than to anything near the ground.
  • SO₂Near the detection floor almost everywhere; only strong point sources clear the noise.

The rasters are served by NASA Worldview / GIBS, and it is worth being precise about what they are: visual products, not retrieval data. NASA takes the Level-2 or Level-3 science files, applies a fixed colour palette, and publishes the result as pre-rendered PNG tiles. The pixel you are looking at is a colour, not a number. You cannot read a value back out of it, the legend under the map is an approximate ramp anchor rather than a measurement scale, and everything is quantised to the palette. For quantitative work you want the underlying granules from NASA Earthdata, not these tiles.

The legend labels are anchors read off NASA's own colormaps, so at least they point at the right magnitudes. NO₂ runs linearly from 0 to 2×10¹⁶ molecules/cm² and saturates there. SO₂ sits on a flat dark floor below 2 Dobson units — which is very nearly the whole planet — and ramps from 2 to 32 DU above it. Both aerosol optical depth products are linear to about 0.68, after which the final stop absorbs everything up to 5.0. A pixel sitting at the top of any of those ramps therefore means at least that much, not that much.

The tiles are also published only to zoom level 6 — about 2.5 km per pixel at the equator. Zooming past that does not reveal more detail; the map simply scales the last real tile up. A crisp-looking edge at street level is an artefact of the resampling.

One overlay on the picker is not a raster at all. The fire toggle draws individual thermal-anomaly detections from NASA FIRMS — MODIS Collection 6.1, the rolling 24-hour global feed, fetched as CSV by this app's own /api/fires route and served to the map as GeoJSON points. Each dot is one roughly 1 km pixel that read anomalously hot at an overpass. That is usually a wildfire or a field being burned, and occasionally a gas flare, a steel works or a sun-glint artefact. A gap is not an absence of fire: cloud blocks the retrieval, and a fire that starts and dies between two overpasses is never seen at all.

Section 03

The surface numbers: CAMS, and what a model cell means

Every number in the readout — every concentration, the index, the twelve-day curve, the coloured dots of the surface grid — comes from the Copernicus Atmosphere Monitoring Service (CAMS), reached through Open-Meteo. CAMS is a global atmospheric composition forecast: emissions inventories and chemical transport physics, constrained by assimilated satellite observations, run forward in time.

Two grids are in play, and which one answers depends on where you clicked. Over Europe, the CAMS regional ensemble resolves about 0.1°, roughly 11 km. Everywhere else, the global product resolves about 0.4°, roughly 40 km. Nothing in the interface marks the boundary, so treat a European reading as several times sharper than an African or South American one.

Open-Meteo hides that boundary a little further by delivering both products on a 0.1° grid. A point in Nairobi and a point in Milan come back at the same spacing, but only the Milan one is resolved at that spacing — the global field has been resampled about four times finer than it can see. Fine spacing in a response is not fine resolution in a model, and no amount of decimal places in a coordinate changes which cell answered.

An 11 km cell is about the width of central Paris. A 40 km cell would cover Paris, its airports and a good deal of countryside in a single number. Neither resolves a street. The difference between a park bench and the kerb of a six-lane road can be a factor of three in NO₂, and it is entirely invisible here — both points return the same cell. Clicking a specific building tells you about the region it sits in, nothing more.

The surface grid overlay makes this explicit: it samples the model on a lattice and draws one soft dot per sample, deliberately not interpolated into a smooth continuous field. It also refuses to draw at all above about 60° of visible longitude, because at that width the samples would be hundreds of kilometres apart and the picture would be an invention.

Section 04

How the US AQI is computed here

The US Air Quality Index is not a measurement; it is a piecewise-linear transform of a concentration onto a 0–500 scale, defined per pollutant by a table of breakpoints. For a concentration C falling in a breakpoint band with concentration limits C₁…C₂ and index limits I₁…I₂, the sub-index is

I = I₁ + (C − C₁) × (I₂ − I₁) / (C₂ − C₁)

That transform is applied here to each of PM₂.₅, PM₁₀, O₃, NO₂, SO₂ and CO, using the concentrations for the current hour. Breakpoints follow 40 CFR Part 58, Appendix G, including the 2024 revision that moved the PM₂.₅ 50-point breakpoint down to 9.0 µg/m³. CAMS reports everything in µg/m³, while the EPA tables for the gases are in ppb or ppm, so those are converted at 25 °C and 1 atm using a molar volume of 24.45 L/mol.

Ozone uses two tables. The 8-hour table the EPA publishes stops at 0.200 ppm, because an 8-hour average above that is not a thing that physically happens; above it, the index is scored on the EPA's separate 1-hour ozone table instead. That table is in turn undefined below 0.125 ppm, which is why it cannot simply replace the 8-hour one everywhere. Clamping to 500 above 0.200 ppm — which this app used to do — made the index jump from 300 to 500 across a fraction of a percent of concentration.

The six bands, their ranges and the guidance attached to them:

BandUS AQIWhat it means
Good050Air quality is clean
Moderate51100Acceptable, with a caveat
Unhealthy for sensitive groups101150Risky if you're sensitive
Unhealthy151200Everyone may feel effects
Very unhealthy201300Health alert
Hazardous301500Emergency conditions

There is a seventh state that is not a band. Where CAMS has no output — open ocean, a model gap, an hour that never published — the reading is null, and the interface renders it in grey as No data. It does not fall into the Good band. The grid and rankings endpoints report those points with the category unknown for the same reason: the absence of a measurement is not evidence of clean air, and nothing here is allowed to make it look like one.

The headline number and the driver are computed differently

This is the one place in the app where two numbers sitting next to each other do not come from the same calculation, so it is worth being exact about it rather than discovering it by being confused.

Headline AQI (the dial)Sub-indices and the driver
Computed byOpen-Meteo, upstreamThis app, from the hourly concentrations
AveragingThe EPA's own windows — 24 h particulates, 8 h ozone and CONone. One instantaneous model hour
AnswersHow bad has the air been over the window the standard defines?Which species is worst at this hour?

Both are maxima over the six pollutants, but they are maxima of two different sets of numbers, so the headline is not the largest sub-index and is frequently nowhere near it. A Delhi hour captured while writing this page read 327 upstream, while the largest sub-index computed here was 181, from PM₁₀ — because a 24-hour PM₂.₅ average carries a whole day of accumulated loading that the current hour has already shed.

The split is deliberate, and each half is the best available answer to its own question. The averaged index is what the standard actually defines and what a health decision should rest on, so it gets the dial. Upstream never says which species is responsible, so attribution has to be computed locally, and the only thing available to compute it from is the current hour. Read the panel as: this is how bad the air is (headline, properly averaged) and this is the best available guess at what is making it bad (driver, this hour).

The practical consequence: the number on the dial is not produced by any of the sub-indices listed beneath it, and the value on the Driver chip is that pollutant's instantaneous sub-index, not a component of the headline. When they disagree, neither is broken. Making them agree would mean recomputing the headline from a single hour, which would make the number people actually act on worse.

Section 05

Why the European index disagrees

The panel also shows the European Air Quality Index, published by the European Environment Agency. It is built on the same idea — take the worst pollutant — but everything else differs: the scale runs 0 to about 100+ rather than 0 to 500, the bands are named rather than numbered (Good, Fair, Moderate, Poor, Very poor, Extremely poor), and the thresholds are set against WHO-informed European limit values rather than the US NAAQS.

The practical consequence is that the two numbers are not comparable and one is not a rescaling of the other. A day that reads 55 on the European scale is not "half" of a US 110. EarthSensing maps the European bands onto the same six colours so that one palette serves both, but the numbers are kept separate and labelled.

Section 06

What this cannot tell you

  • There is no ground-station data in the readout. Every surface number on this site is modelled — not one of them is a measurement taken at that place. Reference monitors are not blended in, not assimilated, and not compared against. Where a local network exists, its readings are the better number and this one should defer to them. Wiring in OpenAQ and WAQI so that a station within about 25 km supersedes the model, with the model as the fallback everywhere else, is the top item on the list of what a next version would add; the repository has the configuration for it in .env.example and nothing that reads it yet.
  • The satellite layers are 1–3 days behind. They describe the recent past, never the current hour. The date control states the lag for the selected product and refuses to ask for a day that cannot have tiles yet.
  • Gaps are shown as gaps. CAMS drops hours, the forecast tail ends earlier for some species than others, and methane is null almost everywhere. Missing values render as an em dash, colour as grey "No data" rather than green, and break the line in the chart rather than being interpolated across — a straight line through a hole is a fabricated measurement.
  • Remote points still return numbers. Click the middle of the Pacific and the model will answer. That answer is a modelled background field, not an observation of that spot, and no one has ever checked it there.
  • A fire detection is a hot pixel, not a fire. The FIRMS feed reports where MODIS saw an anomalous thermal signature in the last 24 hours. It does not report area burned, intensity, or whether anything is still alight — and it misses whatever was under cloud or burned entirely between two overpasses. Detections cluster along overpass swaths for the same reason.
  • This is not medical advice. The health guidance is the EPA's standard band language, not a judgement about you. If you have a respiratory or cardiac condition, your clinician's advice outranks a colour on a map.
Section 07

Sources and attribution

Everything below is public, keyless and free to query. No account, no token, no proprietary feed — as deployed, this site sends an API key to nobody. The optional OpenAQ and WAQI entries in .env.example belong to the ground-station tier described in §06, which is not built; nothing reads them today.

SourceUsed forTerms
NASA EOSDIS GIBS / WorldviewSatellite raster tiles (TROPOMI, MODIS, VIIRS, OMI)Open data; attribution requested
Copernicus CAMSSurface concentrations, indices, forecastsCopernicus licence; free reuse with attribution
NASA FIRMSActive fire detections (MODIS C6.1, rolling 24 hours)Open data; attribution requested
Open-MeteoCAMS and weather delivery, geocoding searchCC BY 4.0; free non-commercial tier
BigDataCloudReverse geocoding — every place name in the readout headerKeyless client endpoint; free tier
OpenFreeMapDark and light vector basemapsFree; tiles built from OpenStreetMap
OpenStreetMap contributorsBasemap geometry and place namesODbL
Esri World ImagerySatellite imagery basemapEsri, Maxar, Earthstar Geographics
WHO Global Air Quality Guidelines 2021Guideline values in the pollutant breakdownWHO publication
Back to the map

Every map view is shareable — the camera, layer, date and selected point all live in the address bar.