Met.no API Client¶
The metno_api module provides a typed Python client for the met.no locationforecast v2.0 API, making it easy to fetch short-range weather forecasts for any global coordinate. It integrates tightly with the rest of weather_tools, returning Pydantic models and ready-to-use pandas DataFrames.
Highlights¶
- ✅ Pydantic-powered queries via
MetNoQueryfor validated coordinates and formats. - ✅ Automatic retries, caching, and backoff to keep requests resilient and efficient.
- ✅ Convenience helpers to aggregate hourly forecasts into daily summaries.
- ✅ DataFrame conversion for both hourly and daily views.
- ✅ Seamless hand-off to
merge_weather_data.merge_historical_and_forecastfor blending with SILO archives.
Requirements¶
- met.no requires a descriptive
User-Agentheader containing a contact address. The client generates a sensible default (weather-tools/<version> (Python <major>.<minor>)), but you should provide your own identifier in production. - Forecast requests do not require authentication, but met.no enforces rate limits—respect their usage policy and cache responses where possible.
Quick Start¶
from weather_tools.metno_api import MetNoAPI
from weather_tools.metno_models import MetNoFormat, MetNoQuery
from weather_tools.silo_models import AustralianCoordinates
# Configure the client (always include your contact details!)
api = MetNoAPI(user_agent="my-app/1.0 (contact: you@example.com)")
# Build a query for a location near Sydney Airport
query = MetNoQuery(
coordinates=AustralianCoordinates(latitude=-33.94, longitude=151.18),
format=MetNoFormat.COMPACT,
)
# Execute and inspect the response metadata
response = api.query_forecast(query)
print(response.get_meta())
Aggregating to Daily Data¶
The API returns hourly forecasts in GeoJSON format. Use MetNoAPI.to_dataframe to convert the payload into either daily summaries or the raw hourly table:
daily_df = api.to_dataframe(response, aggregate_to_daily=True)
hourly_df = api.to_dataframe(response, aggregate_to_daily=False)
- Daily data mirrors the
DailyWeatherSummarymodel, providing min/max temperature, total precipitation, wind statistics, humidity, pressure, cloud cover, and the dominant weather symbol. - Hourly data preserves the original timestamps alongside instantaneous variables and precipitation totals for the next 1/6/12 hours.
Convenience Helper: get_daily_forecast¶
For common use cases you can skip manual query construction:
daily = api.get_daily_forecast(latitude=-33.94, longitude=151.18, days=7)
This method returns a list of DailyWeatherSummary models and automatically truncates the forecast horizon (met.no serves up to 9 days).
Configuration Options¶
Instantiate MetNoAPI with custom behaviour when needed:
api = MetNoAPI(
user_agent="my-app/1.0 (contact: you@example.com)",
timeout=45,
max_retries=4,
retry_delay=1.5,
enable_cache=True,
cache_expiry_hours=2,
log_level="DEBUG",
)
| Parameter | Type | Default | Description |
|---|---|---|---|
user_agent |
str | auto | Identifies your application to met.no |
timeout |
int | 30 | HTTP timeout in seconds |
max_retries |
int | 3 | Attempts for transient failures |
retry_delay |
float | 1.0 | Base delay for exponential backoff |
enable_cache |
bool | True | In-memory response cache toggle |
cache_expiry_hours |
int | 1 | Lifetime for cached responses |
log_level |
str/int | INFO | Logging level for diagnostics |
Use clear_cache() and get_cache_size() to manage cached responses explicitly.
Error Handling¶
The client surfaces clear exceptions:
MetNoUserAgentError— missing/invalid User-Agent (met.no returns HTTP 403).MetNoRateLimitError— too many requests (HTTP 429).MetNoAPIError— other HTTP failures or JSON parsing issues.
Wrap network calls accordingly:
try:
response = api.query_forecast(query)
except MetNoRateLimitError:
logger.warning("Slow down—met.no rate limit hit")
except MetNoUserAgentError as e:
raise RuntimeError("Update your User-Agent") from e
Integration with SILO Data¶
Daily summaries pair naturally with SILO history:
from weather_tools.merge_weather_data import merge_historical_and_forecast
merged = merge_historical_and_forecast(
silo_data=silo_history_dataframe,
metno_data=daily_df,
fill_missing=True,
overlap_strategy="prefer_silo",
)
See Merge Weather Data for a deeper dive into the blending workflow.
Additional Resources¶
- Met.no API documentation
- Met.no Models — Pydantic types used by the client.
- Forecast example notebook — end-to-end usage with SILO integration.