openmeteo-rs 1.0.0

Rust client for the Open-Meteo weather API.
Documentation

openmeteo-rs

Typed async Rust client for the Open-Meteo API.

openmeteo-rs builds Open-Meteo requests with Rust enums instead of raw query strings, validates common parameter mistakes before sending, and decodes weather responses into nullable column-oriented time series.

Quickstart

[dependencies]
openmeteo-rs = "1"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
use openmeteo_rs::{Client, HourlyVar, Result};

#[tokio::main]
async fn main() -> Result<()> {
    let client = Client::new();
    let response = client
        .forecast(52.52, 13.41)
        .hourly([HourlyVar::Temperature2m, HourlyVar::Precipitation])
        .forecast_days(1)
        .send()
        .await?;

    if let Some(hourly) = response.hourly {
        for row in hourly.iter_rows().take(6) {
            println!(
                "{} temp={:?} precipitation={:?}",
                row.time(),
                row.temperature_2m(),
                row.precipitation()
            );
        }
    }

    Ok(())
}

Supported APIs

  • Forecast, including multi-location forecast requests
  • Historical archive
  • Historical forecast
  • Previous model runs
  • Ensemble forecast
  • Seasonal forecast
  • Climate projections
  • Marine forecast
  • Air quality
  • Satellite radiation
  • Flood forecast
  • Geocoding
  • Elevation lookup

Most weather-like endpoints support typed variable selection, units, timezones, cell selection, fixed or relative time windows, JSON decoding, nullable values, and exact-token escape hatches. When Open-Meteo adds a token before the crate exposes it as a typed variant, use the relevant other(...) constructor, for example WeatherModel::other("exact_model_token").

Multi-Location Forecast

use openmeteo_rs::{Client, HourlyVar, Result};

# async fn example() -> Result<()> {
let client = Client::new();
let responses = client
    .forecast_batch([(52.52, 13.41), (47.3769, 8.5417)])
    .hourly([HourlyVar::Temperature2m])
    .forecast_days(1)
    .send()
    .await?;

for response in responses {
    println!("{},{}", response.latitude, response.longitude);
}
# Ok(())
# }

Geocode Then Forecast

use openmeteo_rs::{Client, HourlyVar, Result};

# async fn example() -> Result<()> {
let client = Client::new();
let Some(location) = client.geocode("Zurich").count(1).send().await?.into_iter().next() else {
    return Ok(());
};

let forecast = client
    .forecast(location.latitude, location.longitude)
    .hourly([HourlyVar::Temperature2m])
    .forecast_days(1)
    .send()
    .await?;

println!("{:?}", forecast.hourly);
# Ok(())
# }

Examples

Examples live under examples/<endpoint>/ but keep stable Cargo target names.

cargo run --example forecast_basic
cargo run --example forecast_multi_location
cargo run --example geocode_then_forecast
cargo run --example archive_basic
cargo run --example historical_forecast_basic
cargo run --example previous_runs_basic
cargo run --example ensemble_basic
cargo run --example seasonal_basic
cargo run --example climate_basic
cargo run --example marine_basic
cargo run --example air_quality_basic
cargo run --example satellite_radiation_basic
cargo run --example flood_basic
cargo run --example elevation

Limitations

These capabilities are intentionally not part of the first stable JSON release:

  • FlatBuffers responses
  • Polars or Arrow exports
  • blocking client API
  • batch builders for every endpoint family
  • reverse geocoding, which Open-Meteo does not currently provide
  • CSV/XLSX decoding; request JSON and export from your application instead

Attribution

Open-Meteo data is licensed under CC BY 4.0. Applications using the API should include attribution such as Weather data by Open-Meteo.com.

This crate is MIT licensed.