WeatherAPI returns a feelslike_c field in every current and forecast response. It’s a single number, easy to drop into a UI. It’s also doing something non-obvious: the value switches between the wind chill formula and the heat index formula depending on conditions. If you’re building anything that needs to present or reason about thermal comfort — outdoor apps, construction scheduling, athletic event planning — knowing exactly where that switch happens, and where both formulas fail, matters more than most developers who integrate this field ever check.
Two Formulas, One Field
Wind chill and heat index are not the same calculation applied to different temperature ranges. They measure entirely different physical mechanisms.
Wind chill estimates how quickly a cold environment strips heat from exposed skin. The NWS formula (adopted in 2001, replacing an older NOAA/Environment Canada version) is based on face-level wind speed at 1.5 meters and is only defined for temperatures at or below 10°C and wind speeds above 4.8 km/h. Below those thresholds — calm day, mild temperature — the formula has no valid output and shouldn’t be applied.
Heat index does the opposite: it quantifies how oppressive high humidity makes a hot environment feel by accounting for the body’s reduced ability to shed heat through evaporative cooling. The Rothfusz regression (the version the NWS publishes) is only valid above roughly 27°C and at relative humidity of 40% or higher. Apply it below those thresholds and the output is nonsense — sometimes lower than the actual temperature.
Our pipeline, like most weather APIs, handles this by picking one formula based on current temperature and returning the result as feelslike_c. That’s the right instinct. But the switching logic isn’t visible to the developer consuming the value, and there’s a zone — roughly 10°C to 27°C with moderate wind and moderate humidity — where neither formula is technically valid. In that range, feels-like and actual temperature are often the same number, or very close. That zone is wider than people expect.
What the Response Actually Gives You
A typical /current.json response includes the fields you need to reconstruct the decision logic yourself:
temp_c— actual air temperaturefeelslike_c— the pre-computed composite valuewind_kph— sustained wind speedhumidity— relative humidity as an integer percentage
If you want to know which formula produced the feelslike_c you’re showing, you have to check those underlying fields yourself. The API doesn’t expose a formula selector — it just gives you the result.
Building the Switch in Code
Here’s the logic in plain Python. The thresholds come from NWS definitions, not from us:
def classify_feelslike(temp_c, wind_kph, humidity):
"""
Returns which regime is active: 'wind_chill', 'heat_index', or 'neither'.
Thresholds per NWS: wind chill valid <= 10C and wind > 4.8 kph;
heat index valid >= 27C and RH >= 40%.
"""
if temp_c <= 10 and wind_kph > 4.8:
return 'wind_chill'
elif temp_c >= 27 and humidity >= 40:
return 'heat_index'
else:
return 'neither'
That 'neither' bucket matters. It covers a wide swath of temperate conditions — a dry 20°C afternoon with a light breeze — where perceived thermal comfort is basically what the thermometer says. Surfacing feelslike_c prominently in that context can mislead users into thinking the value always represents a meaningful departure from actual temperature.
The smarter UI move is to only show the deviation when it’s actually doing something:
def feelslike_label(temp_c, feelslike_c, regime):
delta = round(feelslike_c - temp_c, 1)
if regime == 'wind_chill' and delta <= -2:
return f"Feels like {feelslike_c:.1f}°C — wind chill"
elif regime == 'heat_index' and delta >= 2:
return f"Feels like {feelslike_c:.1f}°C — humidity factor"
else:
return f"{temp_c:.1f}°C"
A 2°C delta as the display threshold is defensible: below that, the difference sits inside normal observation noise anyway. Showing “feels like 19.3°C” when the actual temperature is 19.8°C is visual clutter, not information.
The Forecast Case Is Harder
The /forecast.json endpoint includes feelslike_c at hourly granularity. The same switching logic applies, but forecast humidity three days out carries more uncertainty than current observed humidity. The heat index is sensitive to this: a 10-point humidity error at 30°C can shift the heat index output by 3–4°C. Wind chill is less humidity-sensitive but depends on wind forecasts, which are higher-variance beyond day 2 regardless of model.
We blend HRRR, NAM, and GFS depending on location and time horizon. HRRR’s 3km grid helps for near-term temperature and humidity accuracy in complex terrain, but even HRRR uncertainty accumulates fast past 12 hours. For anything beyond 48 hours, treat forecast feelslike_c as directionally useful, not precise — and build your app logic accordingly.
If you’re making scheduling decisions based on forecast feels-like — flagging heat-stress risk for outdoor workers, say — a conservative buffer beats trusting the exact value. Flag potential heat stress risk when forecast heat index exceeds 35°C rather than 40°C. More false positives, but you won’t miss the real events.
Where Both Formulas Break Down
Very high wind at moderate temperatures. Wind chill is technically valid at 10°C with a 60 kph wind, and the output can drop surprisingly — that combination pushes apparent temperature toward 3–4°C. That’s real, but if the station is near a coast or a terrain gap and is picking up locally channeled wind the surrounding area doesn’t experience, the reading can feel exaggerated to users there. This is where station selection quality actually matters, not just the formula.
Humidity above ~90% (saturated air, fog, drizzle). The Rothfusz regression behaves oddly at very high humidity. The NWS publishes adjustment equations for those cases. Our implementation uses the standard regression — accurate for the vast majority of conditions, but it can underestimate perceived heat when humidity is consistently above 90%, the way Gulf Coast summers regularly produce.
Shade vs. sun exposure. Neither formula accounts for solar radiation. A person standing in direct sun at 30°C with 50% humidity feels substantially hotter than the heat index suggests, because heat index assumes shade. NOAA acknowledges this explicitly in their heat index documentation. If you’re building outdoor-exposure tooling, combine heat index with uv_index or solar irradiance as a separate signal rather than treating feelslike_c as the complete picture.
The formula choice is not an implementation detail. It’s what determines whether the number your users are looking at maps to something physically real — or just looks plausible. Pull temp_c, wind_kph, and humidity alongside feelslike_c, classify the regime explicitly, and ask yourself whether your current UI would even show the difference to a user in the 'neither' bucket. Most don’t.
