Obscura

Weather Hourly

Hourly weather by city worldwide from Open-Meteo.

weather_hourly — the dataset name to pass to the Obscura API.

Category Physical Columns 12 Refresh Every 6 hours Point-in-time available_date

What one row means

One hour of observed surface weather (temperature, humidity, precipitation, wind, pressure, cloud cover) for one GeoNames city (pop > 15000), fetched from the Open-Meteo ERA5 archive API. Full-fidelity hourly history; daily aggregates are sampled from the `weather_daily_sampled` VIEW rather than stored separately.

One row per (location, event_time).

Point-in-time availability

Every Obscura dataset carries available_date: the calendar day the publisher made the row available, day-of, with no session rounding. It is the one column a backtest filters on, and it means the same thing on every dataset in the catalog.

For weather_hourly: snapshot: available_date = synced_at::date, the day this row was actually fetched and upserted by the collector (the Open-Meteo archive API has a ~2-day publication lag, so this is the honest capture date, not the observed hour's own date).

Refresh cadence

Obscura refreshes weather_hourly every 6 hours — the most frequent scheduled job that re-collects or re-exports it. This is Obscura's own pipeline cadence, not the upstream publisher's release schedule; when a row became public is recorded per row in available_date.

Schema — 12 columns

The full public column list for weather_hourly, with the meaning of every field. The same schema is served unauthenticated at https://api.obscura.trade/v1/catalog/weather_hourly.

ColumnTypeDescription
locationtext · not nullGeoNames city key formatted "{asciiname}, {ISO country_code}" (worldwide-unique); identifies the fixed lat/lon point this hourly series was fetched for.
event_timetimestamp with time zone · not nullUTC timestamp of the observed hour, parsed from the Open-Meteo archive response's `hourly.time` array.
latitudedouble precision · not nullFixed city-centroid latitude in decimal degrees (GeoNames cities15000.txt), constant across every row for a given location.
longitudedouble precision · not nullFixed city-centroid longitude in decimal degrees (GeoNames cities15000.txt), constant across every row for a given location.
elevationdouble precisionGrid-cell elevation in meters above sea level for the ERA5 cell sampled (Open-Meteo response envelope `elevation`, e.g. 27.0); constant per location, not derivable from stored lat/lon without a DEM.
temp_cdouble precision2-meter air temperature in degrees Celsius for this hour (Open-Meteo `hourly.temperature_2m`).
humidity_pctdouble precision2-meter relative humidity, percent 0-100 (Open-Meteo `hourly.relative_humidity_2m`).
precip_mmdouble precisionTotal hourly precipitation in millimeters, rain + showers + snow water-equivalent (Open-Meteo `hourly.precipitation`).
wind_kphdouble precision10-meter wind speed in km/h, Open-Meteo's default unit (Open-Meteo `hourly.wind_speed_10m`).
pressure_hpadouble precisionSurface-level (station-level, not sea-level-reduced) atmospheric pressure in hectopascals (Open-Meteo `hourly.surface_pressure`).
cloud_pctdouble precisionTotal cloud cover, percent 0-100 (Open-Meteo `hourly.cloud_cover`).
available_datedatePUBLIC-availability date = synced_at::date (the day this row was fetched and upserted). DB-generated STORED column, read-only; the point-in-time column to filter/join on — NEVER the observed hour's own date.

Access weather_hourly

Two delivery paths, one identifier. Both require an Obscura account and an active subscription; the catalog entry and the schema above are public.

import obscura

client = obscura.Client("obs_live_…")

df = client.query(
    dataset="weather_hourly",
    start="2024-01-01",
)

Create a free account Browse all 95 datasets

Frequently asked questions

What is in the weather_hourly dataset?

Hourly weather by city worldwide from Open-Meteo. One hour of observed surface weather (temperature, humidity, precipitation, wind, pressure, cloud cover) for one GeoNames city (pop > 15000), fetched from the Open-Meteo ERA5 archive API. Full-fidelity hourly history; daily aggregates are sampled from the `weather_daily_sampled` VIEW rather than stored separately.

How do I avoid look-ahead bias with weather_hourly?

Filter on weather_hourly.available_date, the day the publisher made the row public. For this dataset that date is derived as follows — snapshot: available_date = synced_at::date, the day this row was actually fetched and upserted by the collector (the Open-Meteo archive API has a ~2-day publication lag, so this is the honest capture date, not the observed hour's own date). A query of the form WHERE available_date <= '<as-of date>' never sees a row before it existed.

In what formats can I get weather_hourly?

As a Parquet bulk export (POST https://api.obscura.trade/v1/download) or as JSON from the typed query API (POST https://api.obscura.trade/v1/query), both with dataset="weather_hourly". The column schema is public at https://api.obscura.trade/v1/catalog/weather_hourly.

How often is weather_hourly updated?

Obscura refreshes weather_hourly on a every 6 hours schedule — that is the most frequent scheduled job that re-collects or re-exports the table. It is Obscura's own pipeline cadence, not the upstream publisher's release schedule; when the publisher makes a row available is described by the availability rule above, and is recorded per row in available_date.

Related datasets

Flight ActivityAircraft positions and flights from the OpenSky network of ADS-B receivers. NWS AlertsActive weather alerts and warnings from the U.S. National Weather Service. USGS EarthquakesEarthquakes worldwide with location, depth and magnitude, from the USGS. Weather DailyDaily weather by city worldwide from Open-Meteo: temperature, precipitation, wind and more.