Build a weather widget with free APIs

Guide · updated November 1st, 2026

A small web page where a visitor types a city and gets the current weather and a three-day forecast. It uses two free APIs from Open-Meteo, needs no API key and no server: the browser calls the APIs directly.

What you need

Open-Meteo offers a forecast API and a geocoding API that turns a place name into coordinates. Both are free without a key and allow calls from any web page (CORS), so a plain HTML file is enough. The free use is for non-commercial projects; see the end of this guide for a commercial site.

Step 1: find the city

The geocoding API searches places by name. count=1 asks for the best match only. The answer has latitude, longitude, name and country for each result, or no results at all when nothing matches.

curl

curl 'https://geocoding-api.open-meteo.com/v1/search?name=Amsterdam&count=1'

Step 2: get the weather

The forecast API takes the coordinates and the values you want. current asks for the weather right now, daily for one value per day, and timezone=auto gives the days in the local time of the place. weather_code is a WMO weather code: 0 is a clear sky, 61 light rain, 95 a thunderstorm.

curl

curl 'https://api.open-meteo.com/v1/forecast?latitude=52.37&longitude=4.89&current=temperature_2m,weather_code,wind_speed_10m&daily=temperature_2m_max,temperature_2m_min&timezone=auto&forecast_days=3'

Step 3: the complete page

Save this as an HTML file and open it in a browser. The script looks up the city, fetches the forecast and writes the result as text, so nothing a visitor types can end up as HTML on the page.

HTML

<form id="weather-form">
  <input id="city" placeholder="City, e.g. Amsterdam" required>
  <button>Show weather</button>
</form>
<p id="weather"></p>

<script>
const weatherCodes = {
  0: 'clear sky', 1: 'mainly clear', 2: 'partly cloudy', 3: 'overcast',
  45: 'fog', 48: 'fog', 51: 'light drizzle', 53: 'drizzle', 55: 'heavy drizzle',
  61: 'light rain', 63: 'rain', 65: 'heavy rain', 71: 'light snow', 73: 'snow',
  75: 'heavy snow', 80: 'rain showers', 81: 'rain showers', 82: 'heavy showers',
  95: 'thunderstorm'
};

async function findCity(name) {
  const url = 'https://geocoding-api.open-meteo.com/v1/search?count=1&name=' + encodeURIComponent(name);
  const data = await (await fetch(url)).json();
  if (!data.results) {
    throw new Error('No place found called ' + name);
  }
  return data.results[0];
}

async function getWeather(latitude, longitude) {
  const url = 'https://api.open-meteo.com/v1/forecast?latitude=' + latitude + '&longitude=' + longitude
    + '&current=temperature_2m,weather_code,wind_speed_10m'
    + '&daily=temperature_2m_max,temperature_2m_min&timezone=auto&forecast_days=3';
  return (await fetch(url)).json();
}

document.getElementById('weather-form').addEventListener('submit', async (event) => {
  event.preventDefault();
  const output = document.getElementById('weather');
  try {
    const city = await findCity(document.getElementById('city').value);
    const weather = await getWeather(city.latitude, city.longitude);
    const now = weather.current;
    const days = weather.daily.time.map((day, i) =>
      day + ': ' + weather.daily.temperature_2m_min[i] + ' to ' + weather.daily.temperature_2m_max[i] + ' °C');
    output.textContent = city.name + ', ' + city.country + ': ' + now.temperature_2m + ' °C, '
      + (weatherCodes[now.weather_code] || 'weather code ' + now.weather_code)
      + ', wind ' + now.wind_speed_10m + ' km/h. ' + days.join('; ') + '.';
  } catch (error) {
    output.textContent = error.message;
  }
});
</script>

Going further

Show the weather where the visitor is: the browser's own navigator.geolocation.getCurrentPosition() gives coordinates, with the visitor's permission, and you can skip step 1.

Do not ask the forecast again on every page view. Keep the answer for a place for, say, 30 minutes, in localStorage or on your server; forecasts do not change by the minute.

For a commercial site, use MET Norway Weather API: it is free also for commercial use, under an open licence that asks for attribution, a User-Agent that names your app and cached results, so call it from your server. For official US forecasts and weather alerts there is the National Weather Service API.

The APIs in this guide