Prerequisites
You need three things:
- Python 3.8 or newer.
- The
requestslibrary. - A free API Ninjas API key — issued instantly, no credit card. If you already have an account, it's on your profile page.
pip install requestsStep 1: Fetch current weather
The endpoint is /v1/weather — pass a city and you get the current observations:
import requests
response = requests.get(
'https://api.api-ninjas.com/v1/weather',
params={'city': 'London'},
headers={'X-Api-Key': 'YOUR_API_KEY'},
timeout=10,
)
response.raise_for_status()
weather = response.json()
print(f"London: {weather['temp']}°C, humidity {weather['humidity']}%")
# London: 14°C, humidity 82%The request on the wire and the full response:
{
"cloud_pct": 75,
"temp": 14,
"feels_like": 13,
"humidity": 82,
"min_temp": 12,
"max_temp": 16,
"wind_speed": 4.63,
"wind_degrees": 240,
"sunrise": 1717645800,
"sunset": 1717703400
}Step 2: Read the response
Every field, with its unit:
| Field | Unit | Meaning |
|---|---|---|
temp, feels_like | °C | Current and apparent temperature. |
min_temp, max_temp | °C | Today's range so far. |
humidity, cloud_pct | % | Relative humidity and cloud cover. |
wind_speed, wind_degrees | m/s, ° | Wind speed and direction (0° = north). |
sunrise, sunset | Unix (UTC) | Today's sun times as timestamps. |
Metric units and Unix timestamps are deliberate — they convert cleanly instead of guessing your locale. The two conversions you'll actually write:
def c_to_f(celsius: float) -> float:
return celsius * 9 / 5 + 32
from datetime import datetime, timezone
weather = get_weather('London')
sunrise = datetime.fromtimestamp(weather['sunrise'], tz=timezone.utc)
print(f"{c_to_f(weather['temp']):.1f}°F, sunrise {sunrise:%H:%M} UTC")Wrapped as a client with the key in an environment variable:
import os
import requests
API_URL = 'https://api.api-ninjas.com/v1/weather'
session = requests.Session()
session.headers['X-Api-Key'] = os.environ.get('API_NINJAS_KEY', 'YOUR_API_KEY')
def get_weather(city: str) -> dict:
"""Return current conditions for a city."""
response = session.get(API_URL, params={'city': city}, timeout=10)
response.raise_for_status()
return response.json()
weather = get_weather('London')
print(f"Temperature: {weather['temp']}°C (feels like {weather['feels_like']}°C)")
print(f"Wind: {weather['wind_speed']} m/s")
print(f"Cloud cover: {weather['cloud_pct']}%")Step 3: Query by coordinates
When the location comes from a browser, GPS, or another API, skip the city name entirely and pass lat/lon:
# Coordinates work in place of a city name — useful straight from
# GPS, the Geocoding API, or the IP Lookup API.
response = session.get(
API_URL,
params={'lat': 51.5074, 'lon': -0.1278},
timeout=10,
)The upstream sources pair naturally: the Geocoding API turns place names into coordinates, and the IP Lookup API turns a visitor's IP into them.
Step 4: Track multiple cities
A weather dashboard is a loop — the shared session keeps it fast:
cities = ['London', 'Tokyo', 'New York', 'Sydney']
for city in cities:
w = get_weather(city)
print(f"{city:10} {w['temp']:>5}°C {w['humidity']:>3}% humidity {w['wind_speed']:>5} m/s")If you schedule this and store each response with a timestamp, you're building your own weather history — the full pattern is in How to Get Historical Weather Data.
Step 5: Handle errors
The common failure is a city name the API doesn't recognize (400) — fall back to coordinates when you can. The rest are the standard pair: bad key (401) and rate limit (429):
from requests.exceptions import HTTPError, RequestException
try:
weather = get_weather('Atlantis')
except HTTPError as error:
status = error.response.status_code
if status == 400:
print('Unknown city — check the spelling, or pass lat/lon instead')
elif status == 401:
print('Missing or invalid API key')
elif status == 429:
print('Rate limit exceeded — cache recent responses')
else:
print(f'HTTP {status}: {error.response.text}')
except RequestException as error:
print(f'Network error: {error}')Where to go from here
The same key serves /v1/weatherforecast for the forward view, the Air Quality API for PM2.5 and ozone at the same coordinates, and our historical weather guide for everything before today. The complete script is below.