Introduction
In this project you will build a real-time weather app using Python, Streamlit, and the free OpenWeatherMap API. Type any city name and instantly see the current temperature, humidity, wind speed, and weather description. This is one of two API-driven builds here — the recipe finder uses the identical requests pattern with a different API.
Prerequisites
- Python 3.8+ — python.org
- Libraries — Install with pip:
pip install streamlit requests
- OpenWeatherMap API Key — Sign up free at openweathermap.org and copy your key from the dashboard.
Step 1: Create the Script
Create weather_app.py and paste the following:
import streamlit as st
import requests
st.set_page_config(page_title="Weather App", page_icon="🌤️")
st.title("🌤️ Real-Time Weather App")
API_KEY = "YOUR_OPENWEATHERMAP_API_KEY"
city = st.text_input("Enter a city name:", placeholder="e.g. Mumbai, London, New York")
def get_weather(city):
url = f"https://api.openweathermap.org/data/2.5/weather?q={city}&appid={API_KEY}&units=metric"
return requests.get(url).json()
if st.button("Get Weather") and city:
data = get_weather(city)
if data.get("cod") == 200:
col1, col2 = st.columns(2)
with col1:
st.metric("🌡️ Temperature", f"{data['main']['temp']} °C")
st.metric("💧 Humidity", f"{data['main']['humidity']}%")
with col2:
st.metric("💨 Wind Speed", f"{data['wind']['speed']} m/s")
st.metric("☁️ Condition", data['weather'][0]['description'].title())
st.success(f"Showing weather for **{data['name']}, {data['sys']['country']}**")
else:
st.error("City not found. Please check the spelling and try again.")
Step 2: Add Your API Key
Replace YOUR_OPENWEATHERMAP_API_KEY with the key you copied from the OpenWeatherMap dashboard.
Step 3: Run the App
streamlit run weather_app.py
Step 4: Use the App
Type a city name and click Get Weather. The app displays current conditions in a clean two-column layout with metric cards.
How It Works
The app follows the standard API request cycle: build a URL with the city and your key, call requests.get(), check response.status_code, then pull fields out of the JSON payload. OpenWeatherMap returns a deeply nested dictionary, so the code extracts weather[0]["description"], main["temp"], and similar paths — always with .get() so a missing field returns None instead of crashing.
A detail worth noticing: the temperature is fetched in metric units by passing &units=metric, which is much easier than converting Kelvin yourself. Display-wise, st.metric() pairs the temperature with a delta arrow, and st.image() renders the icon using the icon code from the response.
Because the rerun model fires a fresh API call on every widget change, real apps add caching — wrapping the fetch in @st.cache_data(ttl=600) means repeated lookups within ten minutes are served instantly. The same caching idea powers the Pandas dashboard.
Key Concepts
requests.get()— Sends the HTTP GET request to the OpenWeatherMap API.response.json()— Parses the JSON response into a Python dictionary.st.metric()— Renders each weather value as a styled metric card.st.columns()— Splits the layout into two side-by-side columns.
What to Try Next
- Show a 5-day forecast using the
/forecastendpoint. - Add weather icons from OpenWeatherMap’s icon library.
- Allow users to switch between Celsius and Fahrenheit using a toggle.
Common Errors & Fixes
-
401 Unauthorized — new API keys take up to a couple of hours to activate, and the key must be passed as
appid, notapi_key. Double-check both before debugging anything else. -
404 city not found — the city name needs the country code for ambiguous names:
"London,UK"not"London". -
KeyError: ‘main’ — you are parsing an error response. Always branch on
status_code == 200before reading weather fields. -
SSL errors on corporate networks — proxy interception; try
requests.get(url, verify=False)temporarily to confirm, then fix the proxy cert store. -
Rate limit exceeded (429) — you are re-fetching on every widget interaction; wrap the API call in
@st.cache_data(ttl=600)so repeat lookups reuse the cache.
FAQ
Is the OpenWeatherMap API free?
Yes — the free tier allows 60 calls/minute and 1,000,000 calls/month, far more than a personal app needs.
Can I show a 5-day forecast?
Yes — use the /forecast endpoint instead of /weather and render the list with st.line_chart() for temperatures, similar to the data dashboard.
How do I hide my API key?
Store it in an environment variable or st.secrets, never in the code you push to GitHub.
Can I use geolocation instead of typing a city?
Yes — get coordinates in the browser with JavaScript and pass them to the /weather endpoint’s lat/lon parameters, which are more precise than city names.