Rust client for the Open-Meteo weather API. Every endpoint of the public API is supported, with an async client by default and a blocking one behind a feature.
- Crates.io: https://crates.io/crates/open-meteo-rs
- Docs.rs: https://docs.rs/open-meteo-rs/
The repository is a workspace of two crates:
| Crate | What it is |
|---|---|
open-meteo-rs |
The reqwest based client. Start here. |
open-meteo-core |
Request building and response parsing with no I/O, no_std + alloc. Use it to bring your own HTTP transport, for instance on an embedded target. |
cargo add open-meteo-rsuse open_meteo_rs::{forecast, Client, Location};
#[tokio::main]
async fn main() -> Result<(), open_meteo_rs::Error> {
let client = Client::new();
let options = forecast::Options {
location: Location { lat: 48.864716, lng: 2.349014 },
current: vec!["temperature_2m".into()],
hourly: vec!["temperature_2m".into(), "precipitation".into()],
daily: vec!["temperature_2m_max".into()],
temperature_unit: Some(forecast::TemperatureUnit::Celsius),
time_zone: Some("Europe/Paris".into()),
forecast_days: Some(3),
..Default::default()
};
let forecast = client.forecast(options).await?;
if let Some(current) = forecast.current {
println!("now ({}): {:?}", current.datetime, current.values["temperature_2m"]);
}
for hour in forecast.hourly.unwrap_or_default() {
println!("{}: {:?}", hour.datetime, hour.values["temperature_2m"].value);
}
Ok(())
}Variable names (temperature_2m, wave_height, river_discharge, ...) are passed through
to the API as-is; the Open-Meteo documentation lists what
each endpoint accepts. Results come back as one record per time step, each holding a map of
variable name to value and unit. Times are local to the requested time zone.
Method on Client |
Options type | Open-Meteo product |
|---|---|---|
forecast |
forecast::Options |
Weather forecast |
archive |
forecast::Options |
Historical weather |
historical_forecast |
forecast::Options |
Historical forecast |
previous_runs |
forecast::Options |
Previous model runs |
ensemble |
ensemble::Options |
Ensemble models, including ensemble means |
seasonal |
seasonal::Options |
Seasonal forecast |
climate |
climate::Options |
Climate change |
marine |
marine::Options |
Marine weather |
air_quality |
air_quality::Options |
Air quality |
satellite_radiation |
satellite_radiation::Options |
Satellite radiation |
flood |
flood::Options |
Flood |
elevation |
elevation::Options |
Elevation |
geocoding |
geocoding::Options |
Geocoding search |
geocoding_get |
geocoding::GetOptions |
Geocoding lookup by id |
Every option struct implements Default, so only the fields you need have to be set.
Enable the blocking feature for a synchronous client with the same methods:
cargo add open-meteo-rs --features blockinglet client = open_meteo_rs::blocking::Client::new();
let forecast = client.forecast(options)?;The blocking client must not be used from inside an async runtime, or it will panic.
Every method returns Result<_, open_meteo_rs::Error>:
Error::Httpwhen the request did not complete (connection, timeout, TLS).Error::Apiwhen the API answered with an error status (the message from the API is included) or with a body that could not be decoded.
Base URLs live in the Endpoints struct. Override the ones you need:
let endpoints = open_meteo_rs::Endpoints {
forecast: "https://customer-api.open-meteo.com/v1/forecast".into(),
..Default::default()
};
let client = open_meteo_rs::Client::new().with_endpoints(endpoints);Pass your key through the apikey field of any options struct.
open-meteo-core has no I/O and no dependency on std. A transport is a GET request plus one
parse call:
use open_meteo_core::{forecast, url, Endpoints, Request};
let endpoints = Endpoints::default();
let options = forecast::Options { hourly: vec!["temperature_2m".into()], ..Default::default() };
let request_url = url(&endpoints.forecast, &options);
let body: Vec<u8> = my_http_get(&request_url)?;
let forecast = forecast::Options::parse(&body)?;Check the status before parsing; on a non-success status, Error::from_status(status, &body)
turns the API's error body into a readable error.
make help # lists every target
make check # format check, lints and offline tests
make lint # workflow, flake, spelling and dependency lints
make ci # everything CI runs
make test-live # smoke tests against the public API