readnoaa provides clean, tidy access to climate and weather data from NOAA (the National Oceanic and Atmospheric Administration) directly from R. No API key required.
The National Oceanic and Atmospheric Administration is a US federal agency responsible for monitoring weather, oceans, and the atmosphere. Its National Centers for Environmental Information (NCEI) is the world’s largest archive of weather and climate data, hosting observations from over 100,000 stations across 180 countries, with some records stretching back to the 1700s.
NCEI maintains the Data Service API, which provides free, open access to this archive. Unlike many government data APIs, it requires no API key - you can start pulling data immediately. The API returns clean CSV with data current to approximately 2-3 days ago.
NOAA’s archive covers a wide range of weather and climate variables. Daily observations include maximum and minimum temperature, precipitation, snowfall, snow depth, and wind speed. Monthly and annual summaries aggregate these into averages and totals. The data spans land-based weather stations, marine buoys, and airport observation sites worldwide.
Beyond current observations, NOAA publishes 30-year climate normals — statistical baselines calculated from the 1991-2020 period that represent “typical” weather for a given location. These are widely used in agriculture, energy, construction, and climate research to understand how current conditions compare to long-term averages. The archive also includes hourly observations, 15-minute precipitation data, and local climatological records for more specialised use cases.
The flagship R package for NOAA data, rnoaa (~3,300 downloads/month at its peak), was archived from CRAN in February 2024 when NOAA deprecated its CDO v2 API. The planned rOpenSci replacement never materialised. The only remaining CRAN package (noaa, 3 functions, ~180 downloads/month) still targets the broken old API.
readnoaa fills this gap by targeting NOAA’s current NCEI Data Service v1 API. It provides dedicated functions for the most common datasets (daily observations, monthly/annual summaries, climate normals) plus a generic fetcher for the full archive. Station discovery functions help you find stations by location or name.
# Install from GitHub
devtools::install_github("charlescoverdale/readnoaa")library(readnoaa)
df <- noaa_daily("USW00094728", "2024-01-01", "2024-01-31",
datatypes = c("TMAX", "TMIN"))
head(df)
#> station date name tmax tmin
#> USW00094728 2024-01-01 NEW YORK CITY CENTRAL PARK, NY 8.9 3.3
#> USW00094728 2024-01-02 NEW YORK CITY CENTRAL PARK, NY 5.0 -1.1
#> USW00094728 2024-01-03 NEW YORK CITY CENTRAL PARK, NY 2.8 -2.2
#> ...stations <- noaa_nearby(51.5, -0.1, radius_km = 25)
head(stations)
#> station name latitude longitude distance_km
#> UKE00105915 LONDON WEATHER CENTRE 51.517 -0.117 1.4
#> UKW00035054 HEATHROW 51.478 -0.449 24.1
#> ...df <- noaa_monthly("USW00094728", "2024-01", "2024-12",
datatypes = c("PRCP"))
head(df)
#> station date name prcp
#> USW00094728 2024-01-01 NEW YORK CITY CENTRAL PARK, NY 87.6
#> USW00094728 2024-02-01 NEW YORK CITY CENTRAL PARK, NY 55.4
#> ...normals <- noaa_normals("USW00094728", "monthly")
head(normals)
#> station name month mly_tavg_normal mly_prcp_normal
#> USW00094728 NEW YORK CITY CENTRAL PARK, NY 01 1.2 86.4
#> USW00094728 NEW YORK CITY CENTRAL PARK, NY 02 2.3 76.5
#> ...# Compare rainfall across three US cities
df <- noaa_monthly(c("USW00094728", "USW00023174", "USW00014739"),
"2024-01", "2024-12", datatypes = "PRCP")
head(df)
#> station date name prcp
#> USW00094728 2024-01-01 NEW YORK CITY CENTRAL PARK, NY US 87.6
#> USW00023174 2024-01-01 LOS ANGELES INTL AP, CA US 52.3
#> USW00014739 2024-01-01 CHICAGO OHARE INTL AP, IL US 44.2
#> ...df <- noaa_annual("USW00094728", "2000-01-01", "2024-01-01",
datatypes = "TAVG")
head(df)
#> station date name tavg
#> USW00094728 2000-01-01 NEW YORK CITY CENTRAL PARK, NY 13.1
#> USW00094728 2001-01-01 NEW YORK CITY CENTRAL PARK, NY 13.4
#> ...# noaa_get() can access any NCEI dataset, including those
# without a dedicated function
df <- noaa_get("global-hourly", station = "USW00094728",
start_date = "2024-07-01", end_date = "2024-07-01")
head(df)
#> station date name ...
#> USW00094728 2024-07-01 NEW YORK CITY CENTRAL PARK, NY ...
#> ...Every NOAA data request needs a station ID. There are two ways to find stations:
1. Search by location using
noaa_nearby():
# Stations within 50 km of Sydney, Australia
noaa_nearby(-33.87, 151.21, radius_km = 50)
#> station name latitude longitude distance_km
#> ASN00066062 SYDNEY OBSERVATORY HILL -33.86 151.21 1.1
#> ASN00066006 SYDNEY AIRPORT AMO -33.95 151.17 9.8
#> ...2. Search by name or bounding box using
noaa_stations():
# Search by name
noaa_stations(text = "Heathrow")
#> station name latitude longitude elevation
#> UKW00035054 HEATHROW 51.478 -0.449 25.3
#> ...
# Search by bounding box (south, west, north, east)
noaa_stations(bbox = c(35, -120, 40, -115))
#> station name latitude longitude elevation
#> USC00040232 BAKERSFIELD MEADOWS FLD 35.433 -119.050 150.0
#> ...| Station | Location |
|---|---|
USW00094728 |
New York City (Central Park) |
USW00023174 |
Los Angeles International Airport |
USW00014739 |
Chicago O’Hare |
UKE00105915 |
London Weather Centre |
UKW00035054 |
London Heathrow |
ASN00066062 |
Sydney Observatory Hill |
JA000047662 |
Tokyo |
GME00111445 |
Berlin-Tempelhof |
FRE00104898 |
Paris-Montsouris |
| Variable | Code | Unit (metric) | Function |
|---|---|---|---|
| Maximum temperature | TMAX |
°C | noaa_daily() |
| Minimum temperature | TMIN |
°C | noaa_daily() |
| Precipitation | PRCP |
mm | noaa_daily(), noaa_monthly() |
| Snowfall | SNOW |
mm | noaa_daily() |
| Snow depth | SNWD |
mm | noaa_daily() |
| Average temperature | TAVG |
°C | noaa_monthly(), noaa_annual() |
| Wind speed | AWND |
m/s | noaa_daily() |
| Normal temperature | MLY-TAVG-NORMAL |
°C | noaa_normals() |
| Normal precipitation | MLY-PRCP-NORMAL |
mm | noaa_normals() |
Use list_datatypes() to discover all available variables
for a given dataset and station.
NCEI applies automated quality control checks to all observations,
flagging approximately 0.3% of values. You can include these flags by
setting include_flags = TRUE:
df <- noaa_daily("USW00094728", "2024-01-01", "2024-01-31",
datatypes = c("TMAX", "TMIN"), include_flags = TRUE)This adds attribute columns alongside each data column containing measurement and quality flag codes. Flags are useful for filtering suspect observations in research workflows.
To include station coordinates (latitude, longitude, elevation) with
each observation, use include_location = TRUE.
| Function | Description |
|---|---|
noaa_daily() |
Daily weather observations |
noaa_monthly() |
Monthly summaries |
noaa_annual() |
Annual summaries |
noaa_normals() |
30-year climate normals (1991-2020) |
noaa_get() |
Generic fetcher for any NCEI dataset |
noaa_stations() |
Search for stations by bbox or text |
noaa_nearby() |
Find stations near a point |
list_datasets() |
Curated table of common datasets |
list_datatypes() |
Available data types for a dataset |
clear_cache() |
Clear local cache |
Daily observations come from the Global Historical Climatology Network - Daily (GHCN-Daily), which integrates data from over 100,000 stations across 180 countries. Monthly and annual summaries are derived from the Global Summary of the Month/Year datasets. Climate normals follow the WMO guidelines for calculating 30-year averages.
NOAA data is produced by the US federal government and is in the public domain. There are no restrictions on its use, redistribution, or modification.
The NCEI Data Service API is free and requires no API key, but it does enforce rate limits. This package automatically throttles requests and retries on rate-limit errors. Daily data requests spanning more than one year are automatically split into yearly chunks to avoid API timeouts. Data is typically available up to 2-3 days behind real time, and station coverage varies — some stations have gaps or limited variable availability. This package is not affiliated with or endorsed by NOAA.