Condition Codes vs. Raw METAR: Why You Should Stop Treating Them as Equivalent

The mapping in the middle that most developers don’t know exists

When you call the WeatherAPI current conditions endpoint and get back a condition object with a numeric code and a text description, that code is not a direct METAR passthrough. It’s the output of a mapping layer we built and maintain ourselves — raw METAR observation goes in, our own numeric condition code comes out. What that layer does, and what it can’t do, matters more than most integrations account for.

METAR present-weather groups are encoded as two-to-three character identifiers: RA (rain), SN (snow), TSRA (thunderstorm with rain), FZRA (freezing rain), BR (mist), FG (fog), and so on. ICAO Annex 3 and the WMO Manual on Codes (WMO-No. 306) define roughly 100 distinct present-weather codes. Our condition code system has far fewer. That compression is the root of every edge case worth thinking about.

What gets lost in compression

METAR intensity qualifiers are the first thing to disappear. A light rain observation (-RA) and a heavy rain observation (+RA) might both resolve to condition code 1189 or 1183, depending on other signals we weigh at mapping time — but neither the raw intensity prefix nor any explicit intensity field surfaces in the standard condition object. If your application cares about the difference between a drizzle and a downpour, precip_mm is doing more work than the condition code is.

Descriptor qualifiers compound this. FZRA (freezing rain) and FZDZ (freezing drizzle) are meteorologically distinct and practically very different — freezing rain is an icing event serious enough that ICAO categorizes it separately in PIREPs; freezing drizzle is an annoyance. Both map into the freezing-precipitation family, but the distinction between them inside our condition system is coarser than the raw METAR makes available. Aviation integrations, road-condition apps, anything deciding whether to flag a de-icing advisory: don’t rely on condition codes alone here.

Vicinity qualifiers (VC) are another edge. VCSH means showers in the vicinity of the station, not at the station. That distinction doesn’t survive cleanly into a condition code describing point-in-time conditions. A developer building a real-time display might show “showers” at a location when the sky directly overhead is clear. Fine for a consumer app; potentially misleading for anything precision-sensitive.

Why we built the mapping ourselves rather than licensing one

Third-party METAR decoding libraries exist and include their own condition mappings. We chose not to use them for this layer. Part of that is a control argument — if a mapping produces something wrong in production, we want to fix it without waiting on an upstream dependency. Part of it is that generic mappings aren’t tuned for the specific condition code vocabulary we ship in API responses, and reconciling two foreign systems produces more edge cases than owning one of them directly.

The obvious tradeoff: we’re also the ones who introduced whatever mistakes are in the current mapping, and fixing them requires us to notice them. The support signal for this is thinner than it should be, because most developers look at the text description and move on without cross-checking against the raw METAR. That’s the right behavior for most use cases — but it means the mapping gets less adversarial testing than it deserves.

Where the condition code system actually holds up

For a consumer-facing weather display that needs to pick an icon, the condition code is the right abstraction. It’s stable, it’s human-readable when paired with the text field, and it’s consistent enough across data sources that you can build icon lookup tables against it without special-casing every possible METAR variant.

It also works well as a coarse routing signal. If your application needs a “bad weather” branch versus a “clear” branch, a threshold on condition code is clean and reliable. The high-salience observations — thunder, heavy precipitation, fog below a certain visibility — map robustly. You’re not going to miss a thunderstorm because the METAR said TSRA and the mapping failed to produce a storm code.

The problem is specifically the middle ground: light winter precipitation, mixed-phase events near 0°C, precipitation-in-vicinity versus precipitation-at-station. That’s where the mapping’s resolution is lowest and where the underlying METAR carries the most signal you can’t recover from the condition code alone.

How to get that signal when you need it

current.condition is not the only place weather state lives in the response. Build your interpretation across multiple fields rather than routing everything through condition code.

  • temp_c and feelslike_c alongside condition code give you enough to distinguish “rain likely staying liquid” from “rain that might be freezing.” Below roughly −2°C with any precipitation code, surface freezing risk is real regardless of whether the condition code specifies freezing rain.
  • precip_mm is your intensity signal. Condition code gives you type; precipitation amount gives you severity. Use both.
  • vis_km fills in where the fog/mist distinction is ambiguous. METAR separates FG (visibility below 1 km) from BR (mist, 1–5 km) as distinct codes; your condition code may or may not preserve that. Visibility from the response directly does not have that problem.
  • wind_kph and gust fields — blowing snow (BLSN) in METAR is a combined wind-and-snow event. A snow condition code alongside gusts above roughly 35–40 kph puts you in blowing-snow territory whether or not the condition code says so explicitly.

One concrete check worth running on your integration

Pull a response for a northern European or Canadian location in January and look at what condition code comes back alongside temp_c values between −1°C and −4°C with non-zero precip_mm. Then cross-reference against the raw METAR for that station — NOAA’s Aviation Weather Center will have it; find the ICAO station ID in the response or nearby. How often does the condition code’s implied precipitation type match what the raw METAR says? Running this check on coastal Scottish and Scandinavian stations — exactly the locations where mixed-phase precipitation is common — the answer is “not always.” It’s not catastrophically wrong, but it’s wrong often enough to matter if mixed-phase detection is part of your product logic.

If you find a systematic gap on specific station types or regions, send it in as a support report rather than silently working around it. That’s the feedback loop that actually improves the mapping.

Condition codes are a useful interface, not a lossless encoding of atmospheric state. Treat them as the routing signal they’re good at — and when your use case sits in that middle ground of light mixed precipitation or vicinity weather, the supplementary fields are there precisely because the code alone isn’t enough.

Scroll to Top