SaaSHub helps you find the best software and product alternatives Learn more →
Wttr.in Alternatives
Similar projects and alternatives to wttr.in
-
-
SaaSHub
SaaSHub - Software Alternatives and Reviews. SaaSHub helps you find the best software and product alternatives
-
stylegan2-pytorch
Simplest working implementation of Stylegan2, state of the art generative adversarial network, in Pytorch. Enabling everyone to experience disentanglement
-
RegExr
RegExr is a HTML/JS based tool for creating, testing, and learning about Regular Expressions.
-
savepagenow
A simple Python wrapper and command-line interface for archive.org’s "Save Page Now" capturing service
-
-
-
-
-
-
-
-
awesome-console-services
A curated list of awesome console services (reachable via HTTP, HTTPS and other network protocols)
-
-
-
-
-
-
-
-
NOTE:
The number of mentions on this list indicates mentions on common posts plus user suggested alternatives.
Hence, a higher number means a better wttr.in alternative or higher similarity.
wttr.in discussion
wttr.in reviews and mentions
Posts with mentions or reviews of wttr.in.
We have used some of these posts to build our list of alternatives
and similar projects. The last one was on 2026-05-03.
-
Building a CLI Tool with Node.js: From Zero to npm
// api.js const CACHE_TTL = 30 * 60 * 1000; // 30 minutes const cache = new Map(); export async function getWeather(location) { const cacheKey = location.toLowerCase(); // Check cache first if (cache.has(cacheKey)) { const { data, timestamp } = cache.get(cacheKey); if (Date.now() - timestamp < CACHE_TTL) { return data; } } // Fetch from free API (wttr.in) const url = `https://wttr.in/${encodeURIComponent(location)}?format=j1`; const response = await fetch(url); if (!response.ok) { throw new Error(`Location "${location}" not found`); } const data = await response.json(); cache.set(cacheKey, { data, timestamp: Date.now() }); return { location: data.nearest_area[0].areaName[0].value, country: data.nearest_area[0].country[0].value, current: data.current_condition[0], forecast: data.weather, }; }
-
AMO Review Process: What Happens After You Submit a Firefox Extension
{ "permissions": ["storage"], "host_permissions": ["https://wttr.in/*"] }
-
Building a Weather Widget for Firefox New Tab: API-Free Approach with wttr.in
async function fetchWeather(location = '') { const url = `https://wttr.in/${encodeURIComponent(location)}?format=j1`; const response = await fetch(url); if (!response.ok) throw new Error(`Weather fetch failed: ${response.status}`); const data = await response.json(); return parseWeatherData(data); } function parseWeatherData(data) { const current = data.current_condition[0]; const today = data.weather[0]; const tomorrow = data.weather[1]; const dayAfter = data.weather[2]; return { temperature: { c: parseInt(current.temp_C), f: parseInt(current.temp_F), }, feelsLike: { c: parseInt(current.FeelsLikeC), f: parseInt(current.FeelsLikeF), }, humidity: parseInt(current.humidity), description: current.weatherDesc[0].value, weatherCode: parseInt(current.weatherCode), forecast: [ parseForecastDay(today), parseForecastDay(tomorrow), parseForecastDay(dayAfter), ], location: data.nearest_area[0], }; } function parseForecastDay(day) { return { date: day.date, maxC: parseInt(day.maxtempC), minC: parseInt(day.mintempC), maxF: parseInt(day.maxtempF), minF: parseInt(day.mintempF), description: day.hourly[4]?.weatherDesc[0]?.value || '', weatherCode: parseInt(day.hourly[4]?.weatherCode || 0), sunrise: day.astronomy[0]?.sunrise || '', sunset: day.astronomy[0]?.sunset || '', }; }
-
Making a Firefox Extension Work Offline — Service Workers vs. Cache API
async function getWeather(city) { const CACHE_KEY = 'weather_cache'; const CACHE_TTL = 10 * 60 * 1000; // 10 minutes // Check cache first const { weather_cache } = await browser.storage.local.get(CACHE_KEY); if (weather_cache && Date.now() - weather_cache.timestamp < CACHE_TTL) { return weather_cache.data; } try { const resp = await fetch(`https://wttr.in/${city}?format=j1`); const data = await resp.json(); // Store in cache await browser.storage.local.set({ [CACHE_KEY]: { data, timestamp: Date.now() } }); return data; } catch (err) { // Return stale cache if available return weather_cache?.data || null; } }
-
Why I Used wttr.in Instead of OpenWeatherMap for My Firefox Extension
const CACHE_DURATION = 30 * 60 * 1000; // 30 minutes async function fetchWeather(city) { const cacheKey = `weather_${city}`; const cached = await browser.storage.local.get(cacheKey); if (cached[cacheKey]) { const { data, timestamp } = cached[cacheKey]; if (Date.now() - timestamp < CACHE_DURATION) { return data; // Return cached data } } // Fetch fresh data const resp = await fetch(`https://wttr.in/${encodeURIComponent(city)}?format=j1`); const data = await resp.json(); // Cache it await browser.storage.local.set({ [cacheKey]: { data, timestamp: Date.now() } }); return data; }
-
How I Built a Firefox New Tab Extension with Pure HTML/CSS/JS (No Frameworks)
async function fetchWeather(city) { const resp = await fetch(`https://wttr.in/${encodeURIComponent(city)}?format=j1`); const data = await resp.json(); return { temp: data.current_condition[0].temp_C, desc: data.current_condition[0].weatherDesc[0].value, forecast: data.weather.slice(0, 3) }; }
-
How I Built a Production AI Agent in Python for $5/month Using Open Source
from langchain.llms import Ollama from langchain.agents import initialize_agent, Tool from langchain.agents import AgentType from langchain.memory import ConversationBufferMemory import requests # Initialize the local model llm = Ollama(model="mistral", base_url="http://localhost:11434") # Define tools your agent can use def get_weather(location: str) -> str: """Fetch weather for a location""" try: response = requests.get( f"https://wttr.in/{location}?format=j1" ) data = response.json() current = data['current_condition'][0] return f"Weather in {location}: {current['temp_C']}°C, {current['weatherDesc'][0]['value']}" except Exception as e: return f"Error fetching weather: {str(e)}" def calculate_something(expression: str) -> str: """Simple calculator tool""" try: result = eval(expression) return f"Result: {result}" except: return "Invalid expression" def search_knowledge_base(query: str) -> str: """Search your own knowledge base""" # This would connect to your vector DB return f"Found information about {query}" # Create tool objects tools = [ Tool( name="Weather", func=get_weather, description="Get current weather for a location" ), Tool( name="Calculator", func=calculate_something, description="Perform mathematical calculations" ), Tool( name="Knowledge", func=search_knowledge_base, description="Search the knowledge base" ), ] # Set up memory memory = ConversationBufferMemory(memory_key="chat_history") # Initialize the agent agent = initialize_agent( tools, llm, agent=AgentType.CONVERSATIONAL_REACT_DESCRIPTION, memory=memory, verbose=True ) # Use the agent result = agent.run("What's the weather in London and what's 25 * 4?") print(result)
-
AI Agents in Rails — Tool Use, Function Calling, and Multi-Step Workflows
# app/services/tool_executor.rb class ToolExecutor def self.execute(tool_name, arguments) case tool_name when "search_documents" search_documents(arguments["query"]) when "get_weather" get_weather(arguments["city"]) when "create_task" create_task(arguments["title"], arguments["priority"] || "medium") else { error: "Unknown tool: #{tool_name}" } end end private def self.search_documents(query) chunks = Retriever.new(query).call results = chunks.map { |c| c.content.truncate(200) } { results: results } end def self.get_weather(city) # In production, call a real weather API response = Net::HTTP.get( URI("https://wttr.in/#{URI.encode_www_form_component(city)}?format=j1") ) data = JSON.parse(response) current = data.dig("current_condition", 0) { city: city, temp_c: current["temp_C"], description: current["weatherDesc"].first["value"] } end def self.create_task(title, priority) task = Task.create!(title: title, priority: priority, status: "pending") { id: task.id, title: task.title, priority: task.priority } end end
-
The Ultimate Guide to Building AI-Powered Web Apps with the Vercel AI SDK in 2026
import { streamText, tool } from 'ai'; import { openai } from '@ai-sdk/openai'; import { z } from 'zod'; export async function POST(req: Request) { const { messages } = await req.json(); const result = streamText({ model: openai('gpt-4o'), messages, tools: { getWeather: tool({ description: 'Get current weather for a location', parameters: z.object({ city: z.string().describe('The city name'), country: z.string().optional().describe('ISO country code'), }), execute: async ({ city, country }) => { // In production: call a real weather API const response = await fetch( `https://wttr.in/${city},${country}?format=j1` ); const data = await response.json(); return { temperature: data.current_condition[0].temp_C, description: data.current_condition[0].weatherDesc[0].value, humidity: data.current_condition[0].humidity, }; }, }), searchDocs: tool({ description: 'Search the internal knowledge base', parameters: z.object({ query: z.string().describe('The search query'), limit: z.number().default(5), }), execute: async ({ query, limit }) => { // Connect to your vector store (Pinecone, pgvector, etc.) const results = await vectorStore.similaritySearch(query, limit); return results.map(r => ({ content: r.pageContent, score: r.score })); }, }), }, maxSteps: 5, // Allow multi-step tool use }); return result.toDataStreamResponse(); }
-
150+ Free APIs You Can Use Without an API Key (2026 Edition)
import requests # Random dog image dog = requests.get('https://dog.ceo/api/breeds/image/random').json() print(dog['message']) # URL to a random dog photo # Weather (no key!) weather = requests.get('https://wttr.in/London?format=j1').json() print(f"London: {weather['current_condition'][0]['temp_C']}C") # Random user profile user = requests.get('https://randomuser.me/api/').json() print(user['results'][0]['name']) # IP geolocation location = requests.get('https://ip-api.com/json/').json() print(f"You're in {location['city']}, {location['country']}")
-
A note from our sponsor - SaaSHub
www.saashub.com | 15 Jun 2026
Stats
Basic wttr.in repo stats
179
29,852
8.0
7 days ago
chubin/wttr.in is an open source project licensed under Apache License 2.0 which is an OSI approved license.
The primary programming language of wttr.in is Go.