惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
B
Blog
Stack Overflow Blog
Stack Overflow Blog
量子位
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Tailwind CSS Blog
MongoDB | Blog
MongoDB | Blog
小众软件
小众软件
博客园 - 三生石上(FineUI控件)
Recent Announcements
Recent Announcements
U
Unit 42
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
腾讯CDC
D
DataBreaches.Net
Microsoft Azure Blog
Microsoft Azure Blog
G
Google Developers Blog
M
MIT News - Artificial intelligence
P
Proofpoint News Feed
罗磊的独立博客
L
LangChain Blog
V
Visual Studio Blog
雷峰网
雷峰网
aimingoo的专栏
aimingoo的专栏
宝玉的分享
宝玉的分享

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
OpenWeatherMap API for Browser Extensions: A Practical Guide
Weather Cloc · 2026-05-04 · via DEV Community

OpenWeatherMap API for Browser Extensions: A Practical Guide

If you're building a browser extension that shows weather data, OpenWeatherMap is the go-to choice. Their free tier is genuinely useful, the API is well-documented, and it works well for extensions that call the API on-demand (rather than from a server).

Here's what I learned building Weather & Clock Dashboard for Firefox.

Getting Started: Free Tier Limits

The OpenWeatherMap free tier gives you:

  • 60 calls per minute
  • 1,000,000 calls per month
  • Access to Current Weather Data API
  • Access to 5 Day / 3 Hour Forecast API

For a new tab extension, even with 10,000 active users opening 20 tabs per day, you'd need ~200,000 calls per day (~6M/month). With 10-minute caching, that drops to ~600,000/month — comfortably under the free limit.

But here's the thing: every user needs their own API key. You cannot bundle your API key in a browser extension that you distribute publicly. The key would be extractable by anyone who reads your extension's source code, and someone would burn through your quota immediately.

The Right Architecture: User-Provided API Keys

// Extension popup/settings page
async function saveApiKey(key) {
  await chrome.storage.local.set({ owmApiKey: key });
}

// In newtab.js
async function getWeather(city) {
  const { owmApiKey } = await chrome.storage.local.get('owmApiKey');

  if (!owmApiKey) {
    // Show API key setup prompt
    showApiKeyPrompt();
    return;
  }

  const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${owmApiKey}&units=metric`;
  const response = await fetch(url);

  if (!response.ok) {
    if (response.status === 401) { showApiKeyError('Invalid API key'); }
    return;
  }

  return response.json();
}

Enter fullscreen mode Exit fullscreen mode

This approach:

  1. Keeps user data private (their key, their account)
  2. Keeps your distribution simple (no backend needed)
  3. Avoids API key extraction from your extension
  4. Puts clear quota responsibility on each user

Smart Caching to Minimize API Calls

For a new tab extension, the user sees the page briefly each tab open. Calling the API every single time is wasteful and hits rate limits fast.

const CACHE_DURATION = 10 * 60 * 1000; // 10 minutes

async function getWeatherWithCache(city) {
  const cacheKey = `weather_${city}`;
  const cached = JSON.parse(localStorage.getItem(cacheKey) || 'null');

  if (cached && (Date.now() - cached.timestamp) < CACHE_DURATION) {
    return cached.data; // Use cached data
  }

  const data = await fetchWeatherFromAPI(city);
  localStorage.setItem(cacheKey, JSON.stringify({
    data,
    timestamp: Date.now()
  }));

  return data;
}

Enter fullscreen mode Exit fullscreen mode

With 10-minute caching, a user opening 100 tabs in an hour only triggers 6 API calls instead of 100.

Handling the 5-Day Forecast

The /data/2.5/forecast endpoint returns 40 data points (every 3 hours for 5 days). For a dashboard, you typically want one reading per day:

async function getForecast(city, apiKey) {
  const url = `https://api.openweathermap.org/data/2.5/forecast?q=${city}&appid=${apiKey}&units=metric&cnt=40`;
  const response = await fetch(url);
  const data = await response.json();

  // Group by day and take noon reading (or first available)
  const byDay = {};
  data.list.forEach(item => {
    const date = new Date(item.dt * 1000);
    const dayKey = date.toDateString();
    const hour = date.getHours();

    // Prefer readings around noon (12-15h)
    if (!byDay[dayKey] || (hour >= 12 && hour <= 15)) {
      byDay[dayKey] = item;
    }
  });

  // Return next 3 days (excluding today)
  const today = new Date().toDateString();
  return Object.entries(byDay)
    .filter(([day]) => day !== today)
    .slice(0, 3)
    .map(([day, data]) => ({
      date: day,
      temp_min: Math.round(data.main.temp_min),
      temp_max: Math.round(data.main.temp_max),
      icon: data.weather[0].icon,
      description: data.weather[0].main
    }));
}

Enter fullscreen mode Exit fullscreen mode

One Icon API Trick You'll Need

OpenWeatherMap weather icons are served at https://openweathermap.org/img/wn/{icon}@2x.png. But if you want nicer icons, you can map their weather condition codes to emoji or custom SVGs:

function weatherCodeToEmoji(iconCode) {
  const code = iconCode.substring(0, 2); // '01', '02', etc.
  const isDay = iconCode.endsWith('d');

  const map = {
    '01': isDay ? '☀️' : '🌙',
    '02': isDay ? '' : '☁️',
    '03': '☁️',
    '04': '☁️',
    '09': '🌧️',
    '10': isDay ? '🌦️' : '🌧️',
    '11': '⛈️',
    '13': '❄️',
    '50': '🌫️'
  };

  return map[code] || '🌡️';
}

Enter fullscreen mode Exit fullscreen mode

Geolocation vs. Manual City Entry

For an extension that shows your local weather, auto-detecting location is ideal — but requires user permission and can fail. Always build both:

async function initWeather() {
  // Try geolocation first
  if ('geolocation' in navigator) {
    navigator.geolocation.getCurrentPosition(
      async (pos) => {
        const { latitude, longitude } = pos.coords;
        const url = `...?lat=${latitude}&lon=${longitude}&appid=${apiKey}`;
        // ... fetch and display
      },
      () => {
        // Geolocation denied or failed
        showCityInputForm();
      },
      { timeout: 5000, maximumAge: 60 * 60 * 1000 } // Cache for 1 hour
    );
  } else {
    showCityInputForm();
  }
}

Enter fullscreen mode Exit fullscreen mode

The Full Stack for Weather & Clock Dashboard

Here's what works in production:

  • API: OpenWeatherMap free tier, user-provided key
  • Caching: 10-minute localStorage cache
  • Units: Auto-detect metric/imperial by location, user-overridable
  • Fallback: Manual city entry if geolocation denied
  • Error handling: Specific messages for 401 (bad key), 404 (city not found), network errors

The extension is open source — feel free to look at the implementation.


Questions about the implementation? Drop them in the comments.