Terrain-Aware Requests: How Elevation Affects the Numbers You Get Back and What to Do About It

Pass a coordinate at 1,200 meters above sea level to a weather API and there’s a real chance the temperature you get back reflects a station sitting several hundred meters lower in an adjacent valley. Not because the API is broken — because observation stations cluster at lower elevations near roads, airports, and towns. The data is where the infrastructure is.

The gap is usually small enough to ignore. Sometimes it isn’t.

Where the Problem Actually Lives

The ICAO standard atmosphere puts the average lapse rate at 6.5°C per 1,000 meters of elevation gain — a useful approximation, not a physical law. It varies with humidity and air mass, but it’s the right order of magnitude for reasoning about station-to-target mismatches.

So if the nearest reporting station sits in a valley at 400m and your user’s coordinate is a ski resort at 1,600m, you’re carrying roughly 7.8°C of uncorrected temperature error before you’ve even considered whether that station’s microclimate matches an exposed ridgeline. For a hiking app surfacing a “feels like” temperature, that’s not cosmetic — it’s the difference between “dress warm” and “turn around.”

Pressure follows the same pattern. Surface pressure drops roughly 1.2 hPa per 100 meters under typical lower-troposphere conditions. If your application runs storm-approach logic on pressure trend, a station 600m lower than your target will report values that are consistently offset. The trend calculation still works; your absolute thresholds won’t.

What We Actually Do

Our METAR station-selection logic scores candidates on distance, elevation delta, and a consistency check against neighboring stations — not pure nearest-by-distance. On top of that, we apply a lapse-rate temperature correction when there’s a meaningful elevation gap between the selected station and the requested coordinate. That handles most coastal and moderate-terrain cases reasonably well.

The limits are real, though. No correction turns a single valley station into a reliable reading for a summit 40km away with nothing in between. The adjustment is a general atmospheric average, not a model of the specific local terrain. In practice it still falls short at high-altitude Alpine and Rocky Mountain locations, remote highland plateaus, and anywhere station density is genuinely sparse — meaning the nearest station is far enough away that even good scoring logic is working with a weak starting point.

The elevation field in our API response is worth checking. If the coordinate you sent sits at 2,000m but the conditions come from a station at 800m, the temperature is already adjusted — imperfectly. Knowing the gap exists helps you decide whether to trust the reading or apply your own correction layer on top.

Building Your Own Correction Layer

If you know the actual elevation of the point your user cares about — from a DEM tile, a geocoding response, your own data — a simple post-processing step covers most cases:

// elevation_diff in meters: positive means target is higher than the API station
function correctTemperatureForElevation(tempC, stationElevationM, targetElevationM) {
  const LAPSE_RATE = 0.0065; // °C per meter
  const elevationDiff = targetElevationM - stationElevationM;
  return tempC - (LAPSE_RATE * elevationDiff);
}

That’s a dry adiabatic approximation. It runs slightly warm in saturated conditions — inside cloud or during heavy precipitation — where the moist adiabatic lapse rate is closer to 4–5°C per 1,000m. For most surface-level applications it’s good enough, and it’s meaningfully better than using the raw number unchanged.

For pressure, the hypsometric formula gives a more rigorous answer, but for small elevation differences the linear approximation holds:

function correctPressureForElevation(pressureMb, stationElevationM, targetElevationM) {
  const elevationDiff = targetElevationM - stationElevationM;
  return pressureMb - (elevationDiff * 0.012); // ~1.2 hPa per 100m
}

Getting the station elevation is the harder half of this. Our API responses don’t currently surface the contributing station’s elevation directly in the JSON — the location block gives you the elevation of the requested coordinate, not the observation source. For a precise correction you’d need to cross-reference the METAR station identifier against NOAA’s station metadata or the ICAO airport database, both publicly available.

Precipitation Type Is the Quiet Casualty

Temperature errors cascade into precipitation-type calls. Near the rain/snow boundary — roughly 0°C to 2°C surface temperature — a 3°C error is enough to flip rain to snow or vice versa. At 6.5°C per 1,000m, every 500m of elevation difference between your target and the reporting station is a potential misclassification risk during winter boundary-layer events.

Our condition code mapping from raw METAR handles the cases where the METAR itself reports mixed precipitation — we map those explicitly rather than letting them fall into a generic bucket. But when the METAR reports rain because the station is at 600m and your actual location is at 1,100m in freezing air, the condition code says rain, the corrected temperature says snow, and your app has to pick a signal. The corrected temperature is almost always closer to ground truth at the target coordinate.

Which Use Cases Should Actually Care

Flat terrain at low elevation — the US Midwest, most of the UK midlands, the Netherlands — this is rarely a meaningful problem. Dense station networks and minimal elevation variation mean nearest-station logic with correction produces solid results.

Mountain resort apps, trail running or hiking tools, alpine agriculture (vineyards on slopes, orchards at varying altitude), any product serving both valley-floor and hillside users: leaving this uncorrected will generate support tickets eventually. They’ll come in framed as “your weather is wrong” rather than “your elevation correction is missing,” which makes them genuinely hard to diagnose without knowing to look for the station gap in the first place.

Aviation applications are a separate case — pressure altitude and density altitude concerns go beyond a simple surface correction, and certified ICAO METAR sources are the right anchor there, not a corrected surface reading.

One Thing Worth Checking Before You Deploy

Pull location.lat, location.lon, and temp_c from a handful of real API responses for your highest-elevation target coordinates. Then check those coordinates against a public DEM — SRTM or the Copernicus DEM both cover global land at 30–90m resolution — and compare the elevation to what the temperature implies. If readings are consistently warmer than local forecasts or nearby mountain weather services would suggest, the station elevation gap is almost certainly why. Quantify that gap before deciding whether you need a correction layer. You might not — but you’ll know.

Scroll to Top