The Problem With Relative Humidity as a Standalone Field
If you’re building irrigation, crop monitoring, or outdoor scheduling on top of WeatherAPI, you’ve probably reached for humidity at some point. It’s right there in the response — clean integer, easy to display. But relative humidity without temperature context is almost meaningless for calculating actual atmospheric water demand. A reading of 60% RH at 15°C is a completely different physical situation from 60% RH at 35°C. The air at 35°C holds nearly three times as much moisture at saturation, so 60% of that is far more drying than 60% at the cooler temperature.
What actually drives water loss from soil and plant surfaces is vapor pressure deficit (VPD) — the gap between how much moisture the air could hold and how much it currently holds. And beyond VPD, a proper evapotranspiration estimate needs solar radiation, wind, and temperature too. WeatherAPI gives you all of these in the hourly forecast payload. The question is how to combine them usefully.
What ET₀ Actually Is and Why It Matters
Reference evapotranspiration (ET₀) is the rate of water loss from a standardized reference surface — typically short grass — under given atmospheric conditions, expressed in mm/day or mm/hour. The FAO-56 Penman-Monteith equation is the standard method, documented in FAO Irrigation and Drainage Paper No. 56 (Allen et al., 1998), and it’s what most irrigation scheduling systems use as their foundation.
The simplified hourly form needs: temperature, dew point (or humidity, from which you derive dew point), wind speed, net radiation, and atmospheric pressure. WeatherAPI provides all of these either directly or derivable from the hourly payload.
The Fields You Need from WeatherAPI
From a standard /v1/forecast.json or /v1/history.json hourly response, you want:
temp_c— air temperature in Celsiushumidity— relative humidity as an integer percentagewind_kph— wind speed at 10m (needs adjustment to 2m for FAO-56)pressure_mb— atmospheric pressure in millibars/hPauv— UV index, useful as a rough solar radiation proxycloud— cloud cover percentage (for radiation estimation when you need more precision)
The payload doesn’t include net radiation directly. That’s the real gap — and it’s where the approach requires the most care.
Deriving the Key Intermediary Values
Step 1: Saturation and Actual Vapor Pressure
Saturation vapor pressure (e_s, in kPa) from temperature, using the Tetens approximation:
e_s = 0.6108 * Math.Exp((17.27 * temp_c) / (temp_c + 237.3))
Actual vapor pressure (e_a) from relative humidity:
e_a = (humidity / 100.0) * e_s
VPD is just e_s - e_a. If you want to expose this directly as a plant stress indicator, values above roughly 1.5 kPa start to restrict stomatal conductance in most crops. Above 3 kPa you’re looking at significant stress in sensitive plants — a reasonable threshold to alert on.
Step 2: Wind Speed Height Correction
FAO-56 wants wind at 2m. WeatherAPI reports wind_kph at 10m. The log wind profile correction is:
wind_2m = wind_kph * (4.87 / Math.Log(67.8 * 10 - 5.42))
That denominator evaluates to a constant — roughly 3.738 — so this simplifies to multiplying wind_kph by about 0.748 and converting to m/s (divide by 3.6). Skipping this correction overstates wind influence in the ET₀ formula by roughly 25–30%. That error is minor in calm, humid conditions and consequential in windy, arid ones — exactly the conditions where ET₀ estimates matter most.
Step 3: Net Radiation — The Hard Part
Proper net radiation (R_n) requires shortwave incoming radiation measured directly, plus a net longwave component. WeatherAPI doesn’t expose R_n directly, so there’s a choice to make about how to approximate it.
The uv field is a rough proxy for solar irradiance, but the relationship between UV index and total solar irradiance degrades under partial cloud cover in a nonlinear way — it’s a coarse approximation at best. A more defensible path: use latitude and day-of-year to calculate theoretical extraterrestrial radiation (R_a) from the FAO-56 tables, then attenuate by cloud cover:
// R_a from FAO-56 equations (MJ/m²/day) — simplified
// For hourly: divide daily R_a by daylight hours
double R_s = R_a * (0.25 + 0.50 * (1 - cloud_cover_fraction));
double R_n = 0.77 * R_s; // accounting for albedo of ~0.23 for reference grass
This is still an estimate. If your use case is high-stakes — scheduling irrigation for a commercial vineyard, calculating insurance-grade water deficits — verify against nearby ASOS or agricultural weather station actinometer readings rather than relying on this alone.
Putting It Together: Simplified Hourly ET₀
The FAO-56 hourly ET₀ formula:
// All units: temperature in °C, pressure in kPa, wind in m/s, R_n in MJ/m²/hour
double delta = 4098 * e_s / Math.Pow(temp_c + 237.3, 2); // slope of vapor pressure curve
double gamma = 0.000665 * (pressure_mb / 10.0); // psychrometric constant
double ET0 = (0.408 * delta * R_n + gamma * (37.0 / (temp_c + 273)) * wind_ms * (e_s - e_a))
/ (delta + gamma * (1 + 0.34 * wind_ms));
Result is in mm/hour. Sum across daylight hours for a daily estimate.
One thing that trips people up: the 37.0 numerator in the wind term is specific to hourly timesteps. The daily formula uses 900. Using the wrong coefficient produces values that look plausible but are off by a meaningful factor — it won’t throw an error, it’ll just quietly give you wrong irrigation schedules.
What This Gets You — and What It Doesn’t
For irrigation scheduling, crop stress alerting, or estimating water balance across a growing season, this approach gives you something genuinely useful without requiring a dedicated agri-weather data license. On a free-tier WeatherAPI key you can pull 7 days of hourly forecast and build a week-ahead ET₀ curve — enough to drive irrigation decisions for most smallholder or garden-scale applications.
For historical validation — backtesting a growing season, for example — use /v1/history.json with daily date stepping. The field structure is identical, and multi-year data is available on paid plans. We’re also looking at a bulk historical licensing option that would make seasonal analysis cheaper to run at scale, though that’s not in production yet.
The honest caveat: derived ET₀ from a general-purpose weather API will consistently underperform a purpose-built agri-station running a dedicated datalogger with a pyranometer and a properly sited anemometer. The physics in the formula is correct; input data quality is the constraint. That gap is small on clear, stable days and larger during complex conditions — convective activity, fog, rapid frontal passage. Cross-validate against local agricultural extension data before making consequential decisions.
Also worth knowing: both the wind height correction and the radiation estimate are sensitive to the quality of cloud and wind_kph, which themselves inherit uncertainty from METAR station selection and model blending. In complex terrain or near coastlines those fields carry more noise than they do over flat agricultural land — which, fortunately, is where most irrigation use cases live anyway.
Start by logging your derived ET₀ against whatever ground truth you have access to. Even a basic tipping-bucket rain gauge and a hobby-station reading is enough to sanity-check the magnitude. The formula is well-established; the failure mode is almost always in the input fields, not the math. If your numbers look off, check the radiation path first — that’s where the approximation is coarsest.
