NewConnect Claude, Gemini, ChatGPT, and other AI agents to API Ninjas via our MCP server

How to Get Historical Weather Data

Weather APIUpdated August 28, 2026
Create a free API key and it will be pre-filled into every code sample on this page. No credit card required.
There are two ways to get historical weather data: download the past from a public archive, or record the present yourself by logging a live feed on a schedule. Serious projects usually do both — an archive for the backfill, a Weather API logger for a dataset you fully control going forward. This guide has working Python for each route.

Where historical weather data lives

SourceCoverageTypeBest for
NOAA NCEISome stations to the 1800sOfficial station recordsUS locations; legal- and research-grade history
Open-Meteo archive1940 → present, global gridReanalysis (modeled)Any coordinates worldwide, station or not
MeteostatVaries by stationAggregated station recordsPython-native access to global stations
API Ninjas Weather APIFrom when you start loggingLive observations you recordExactly your locations, intervals, and fields

The key distinction is station versus reanalysis data. Station records are real instrument readings — authoritative, but only where a station exists. Reanalysis reconstructs a continuous global grid from observations and models — available everywhere, but modeled rather than measured.

Prerequisites

Every route below needs just:

  • Python 3.8 or newer with the requests library.
  • For Step 3 only: a free API Ninjas API key — issued instantly, no credit card; existing accounts find it on the profile page. The NOAA and Open-Meteo archives need no key at all.
shell
pip install requests

Step 1: Download official records from NOAA

NOAA's National Centers for Environmental Information serve daily summaries over plain HTTP — pass a station ID and a date range:

noaa_history.py
import requests response = requests.get( 'https://www.ncei.noaa.gov/access/services/data/v1', params={ 'dataset': 'daily-summaries', 'stations': 'USW00094728', # New York — Central Park 'startDate': '2020-01-01', 'endDate': '2020-12-31', 'dataTypes': 'TMAX,TMIN,PRCP', 'units': 'metric', 'format': 'json', }, timeout=30, ) records = response.json() print(records[0]) # {'DATE': '2020-01-01', 'STATION': 'USW00094728', # 'TMAX': '4.4', 'TMIN': '-1.0', 'PRCP': '0.0'}

TMAX/TMIN are the daily temperature extremes and PRCP is precipitation. Airport stations (IDs starting USW) have the longest, cleanest records — find IDs with NOAA's station search.

Step 2: Download reanalysis history for any coordinates

For places without a convenient station — or outside the US — the Open-Meteo archive serves modeled daily and hourly values back to 1940 for any point on Earth, free for non-commercial use:

reanalysis.py
response = requests.get( 'https://archive-api.open-meteo.com/v1/archive', params={ 'latitude': 51.5074, 'longitude': -0.1278, 'start_date': '2010-01-01', 'end_date': '2020-12-31', 'daily': 'temperature_2m_max,temperature_2m_min,precipitation_sum', 'timezone': 'UTC', }, timeout=30, ) daily = response.json()['daily'] print(daily['time'][0], daily['temperature_2m_max'][0])

Have an address instead of coordinates? Geocode it first — see How to Convert a City to Latitude and Longitude.

Step 3: Log your own history going forward

Archives end at yesterday and contain whatever fields the archive chose. For dashboards, ML training data, or monitoring specific sites, the most useful history is the one you record yourself: call the Weather API on a schedule and append every observation to a database:

log_weather.py
import os import sqlite3 import time import requests session = requests.Session() session.headers['X-Api-Key'] = os.environ.get('API_NINJAS_KEY', 'YOUR_API_KEY') SCHEMA = """CREATE TABLE IF NOT EXISTS observations ( city TEXT, observed_at INTEGER, temp REAL, feels_like REAL, humidity REAL, wind_speed REAL, cloud_pct REAL )""" def log_weather(city: str) -> None: """Fetch current conditions and append them to the local history.""" data = session.get( 'https://api.api-ninjas.com/v1/weather', params={'city': city}, timeout=10, ).json() with sqlite3.connect('weather_history.db') as db: db.execute(SCHEMA) db.execute( 'INSERT INTO observations VALUES (?, ?, ?, ?, ?, ?, ?)', (city, int(time.time()), data['temp'], data['feels_like'], data['humidity'], data['wind_speed'], data['cloud_pct']), ) for city in ['London', 'Tokyo', 'New York']: log_weather(city) print('Logged 3 observations')

Schedule it with cron and the dataset builds itself:

crontab
# Log observations every hour, on the hour 0 * * * * /usr/bin/python3 /home/app/log_weather.py

After a few weeks you have a gap-free, per-hour record for exactly the places you care about — something no public archive offers.

Step 4: Add the forward view

The same key serves /v1/weatherforecast, so one pipeline can store yesterday's observations next to tomorrow's forecast — which is exactly what you need to score forecast accuracy against what actually happened:

forecast.py
forecast = session.get( 'https://api.api-ninjas.com/v1/weatherforecast', params={'lat': 51.5074, 'lon': -0.1278}, timeout=10, ).json()

Where to go from here

Extend the logger with the Air Quality API to record PM2.5 and ozone alongside the weather, and the Geocoding API to resolve new place names as you add them. The complete logger script is below.

weather_history.py

The logger from this guide: schedule it with cron and it appends observations for your cities to SQLite.

Frequently asked questions

How far back does historical weather data go?

Station archives reach furthest — some NOAA stations have daily records back to the late 1800s. Reanalysis datasets like the one behind Open-Meteo start in 1940 and cover every location on a grid, even where no station existed.

Is historical weather data free?

Largely yes. NOAA NCEI is US government open data, Open-Meteo’s archive is free for non-commercial use, and the API Ninjas Weather API has a free tier for building your own log.

Why do two sources disagree about the same day?

Station data is what one instrument measured at one point; reanalysis models a grid cell that can average several kilometres. Elevation, station moves, and interpolation all create small gaps. For legal or insurance purposes, use the official station record.

Can I get history for an exact street address?

Weather is not measured per address — use the nearest station, or reanalysis at the address’s coordinates. The Geocoding API converts the address to latitude and longitude first.

Does the API Ninjas Weather API return past weather?

It returns current observations and forecasts (/v1/weather and /v1/weatherforecast). Archives cover dates before you started collecting; from the moment your logger runs, your own dataset covers every interval you choose.