Building a Weather App in 2026? Here's the Free API Stack I'd Use
· weather
Open-Meteo for forecasts, Nominatim for location lookup, Open-Meteo Air Quality for pollution data. Code snippets and gotchas included.
The free API stack for a weather app in 2026: Open-Meteo for forecasts (10,000 calls/day, no key), Nominatim for address-to-coordinates (1 req/sec, no key), and Open-Meteo Air Quality for pollution data (10,000 calls/day, no key, same API design). Total cost: $0.
I'll walk through the integration, the response shapes, and the specific gotchas that will bite you if you don't know about them.
Step 1: Geocode the User's Location
Before you can get weather, you need coordinates. If your app accepts a city name or address, Nominatim converts it to lat/lng:
async function geocode(query) {
const url = new URL("https://nominatim.openstreetmap.org/search");
url.searchParams.set("q", query);
url.searchParams.set("format", "json");
url.searchParams.set("limit", "1");
const res = await fetch(url, {
headers: {
"User-Agent": "MyWeatherApp/1.0 ([email protected])"
}
});
const results = await res.json();
if (!results.length) return null;
return { lat: parseFloat(results[0].lat), lon: parseFloat(results[0].lon) };
} Cache this result. A city name maps to the same coordinates every time — there's no reason to hit Nominatim again for 'London' if you already have its coordinates.
See /nominatim for live status and /tutorial/nominatim for the full tutorial including rate limit handling.
Step 2: Fetch the Forecast from Open-Meteo
Open-Meteo's response has two top-level keys you'll use: `current` (current conditions) and `hourly` (hourly forecast for the next 7 days). Request only what you need — each parameter adds response size.
async function getForecast(lat, lon) {
const url = new URL("https://api.open-meteo.com/v1/forecast");
url.searchParams.set("latitude", lat);
url.searchParams.set("longitude", lon);
// Current conditions
url.searchParams.set("current", [
"temperature_2m",
"apparent_temperature",
"precipitation",
"weathercode",
"windspeed_10m"
].join(","));
// Hourly for next 24 hours (index 0-23)
url.searchParams.set("hourly", "temperature_2m,precipitation_probability,weathercode");
url.searchParams.set("forecast_days", "2");
url.searchParams.set("timezone", "auto"); // infer from coordinates
const res = await fetch(url);
const data = await res.json();
return {
current: data.current,
hourly: {
times: data.hourly.time.slice(0, 24),
temp: data.hourly.temperature_2m.slice(0, 24),
precip_prob: data.hourly.precipitation_probability.slice(0, 24),
weathercode: data.hourly.weathercode.slice(0, 24)
}
};
} The `weathercode` follows the WMO standard (0 = clear sky, 61/63/65 = rain by intensity, 71/73/75 = snow). Open-Meteo's docs at https://open-meteo.com/en/docs include the full WMO code table.
See /open-meteo for live status.
Step 3: Add Air Quality (Optional)
Open-Meteo's Air Quality API uses identical parameter syntax but a different base URL:
async function getAirQuality(lat, lon) {
const url = new URL("https://air-quality-api.open-meteo.com/v1/air-quality");
url.searchParams.set("latitude", lat);
url.searchParams.set("longitude", lon);
url.searchParams.set("current", "pm10,pm2_5,european_aqi");
const res = await fetch(url);
const data = await res.json();
return data.current; // { pm10, pm2_5, european_aqi, ... }
} The `european_aqi` value maps to the EU Air Quality Index (1–5 scale: Good, Fair, Moderate, Poor, Very Poor). The same 10,000 calls/day limit applies but it's a separate quota from the weather API. See /open-meteo-air-quality for current status.
When the Free Stack Breaks Down
The free stack isn't suitable for: commercial applications with >1,000 DAU (you'll hit Open-Meteo's free tier), hyperlocal precipitation nowcasting (none of the free APIs match Dark Sky's sub-km resolution), or severe weather alerting for production use (NOAA alerts are great for the US but not global).
The natural paid upgrade path: Open-Meteo commercial plan ($10–$50/month) for volume, OpenCage ($50/month) if geocoding volume exceeds what Nominatim can handle comfortably, and Tomorrow.io ($19/month) if you need hyperlocal features.
For the full weather API comparison, see /category/weather and /compare/open-meteo-vs-openweathermap.