DEV Community

Weather Clock Dash
Weather Clock Dash

Posted on

How to Build a Weather Extension Without an API Key

How to Build a Weather Extension Without an API Key

Most weather tutorials start with "sign up for a free tier API key." Then your project depends on that key staying valid, rate limits not changing, and the provider not getting acquired.

There's a better way.

Open-Meteo: Free weather data, no sign-up

Open-Meteo is an open-source weather API that:

  • Requires zero authentication
  • Has no rate limits for non-commercial use
  • Returns structured JSON
  • Uses ECMWF and GFS forecast models

The only thing you provide: latitude and longitude.

The complete fetch

async function getWeather(lat, lon) {
  const params = new URLSearchParams({
    latitude: lat,
    longitude: lon,
    current_weather: true,
    daily: 'weathercode,temperature_2m_max,temperature_2m_min',
    forecast_days: 4,
    timezone: 'auto'
  });

  const res = await fetch(`https://api.open-meteo.com/v1/forecast?${params}`);
  if (!res.ok) throw new Error(`Weather API error: ${res.status}`);
  return res.json();
}
Enter fullscreen mode Exit fullscreen mode

Getting user location

The Geolocation API is built into browsers. In an extension context:

function getPosition() {
  return new Promise((resolve, reject) => {
    navigator.geolocation.getCurrentPosition(
      pos => resolve({ lat: pos.coords.latitude, lon: pos.coords.longitude }),
      err => reject(err),
      { timeout: 10000 }
    );
  });
}
Enter fullscreen mode Exit fullscreen mode

Decoding weather codes

Open-Meteo returns WMO weather codes (0-99). Here's a minimal decoder:

const WEATHER_CODES = {
  0: { label: 'Clear sky', icon: '☀️' },
  1: { label: 'Mainly clear', icon: '🌤️' },
  2: { label: 'Partly cloudy', icon: '' },
  3: { label: 'Overcast', icon: '☁️' },
  45: { label: 'Foggy', icon: '🌫️' },
  48: { label: 'Depositing rime fog', icon: '🌫️' },
  51: { label: 'Light drizzle', icon: '🌦️' },
  61: { label: 'Slight rain', icon: '🌧️' },
  71: { label: 'Slight snow', icon: '🌨️' },
  80: { label: 'Slight rain showers', icon: '🌦️' },
  95: { label: 'Thunderstorm', icon: '⛈️' },
};

function decodeWeather(code) {
  return WEATHER_CODES[code] || { label: 'Unknown', icon: '🌡️' };
}
Enter fullscreen mode Exit fullscreen mode

Putting it together in a browser extension

The manifest.json only needs one permission and one external host:

{
  "manifest_version": 2,
  "permissions": ["storage", "geolocation"],
  "content_security_policy": "script-src 'self'; connect-src 'self' https://api.open-meteo.com"
}
Enter fullscreen mode Exit fullscreen mode

Then in your new tab page:

async function init() {
  try {
    const { lat, lon } = await getPosition();
    const data = await getWeather(lat, lon);
    renderWeather(data);
  } catch (err) {
    if (err.code === 1) {
      // PERMISSION_DENIED — show fallback
      renderOffline();
    } else {
      renderError(err.message);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Caching to avoid hitting the API on every new tab

Opening a new tab on every keystroke would spam the API. Cache with a TTL:

async function getCachedWeather(lat, lon) {
  const cached = await browser.storage.local.get('weatherCache');
  const cache = cached.weatherCache;

  if (cache && Date.now() - cache.timestamp < 10 * 60 * 1000) {
    return cache.data; // 10-minute TTL
  }

  const data = await getWeather(lat, lon);
  await browser.storage.local.set({
    weatherCache: { data, timestamp: Date.now() }
  });
  return data;
}
Enter fullscreen mode Exit fullscreen mode

The result

This is exactly how Weather & Clock Dashboard works — a Firefox new tab replacement that shows live weather, a 3-day forecast, world clocks, and a search bar. No API keys, no accounts, no backend.

All ~500 lines of it are MIT licensed if you want to fork and extend it.


The broader lesson: before reaching for an API-key service, check if there's an open alternative. Open-Meteo isn't the only one — Nominatim for geocoding, OpenStreetMap for maps, Open Notify for ISS location. The ecosystem of no-auth APIs is larger than most people realize.

Top comments (0)