The Open-Meteo weather API uses FlatBuffers to encode API responses efficiently. The compiled schema files for various programming languages can be found in this repository.
The biggest advantage of FlatBuffers is that large floating point arrays can be encoded directly instead of expensive transformation to JSON ASCII. Especially for historical weather data processing is significantly faster. But also for displaying a regular weather forecast on low-power devices, binary data encoding saves energy.
The FlatBuffers schema definition can be found in the ./flatbuffers directory. Only non-breaking changes are accepted. Binary compatibility is ensured. Every change will be announced in new release following semantic versioning.
The compiled schema files do not contain any code to perform HTTP calls. They are intent to be used by developers to build client libraries.
More information on how to use the compiled schema files can be found in the directories for each programming language
- Swift via Swift Package Manager
- Python via PIP
- TypeScript / JavaScript via NPM
- Java via Maven Central
- C#
Not all programming languages are supported yet. It is a time-intensive process to validate all languages. Please open a issue ticket to ask for an additional language and/or package distribution system.
Open-Meteo offers various APIs. Each API endpoint is using different FlatBuffers schemas to encode its API response. This enables strict typing. E.g. Weather data APIs offer offers different variables while the Geocoding API returns a different structure. Per default, the Open-Meteo API returns JSON, but specifying &format=flatbuffers
in the URL return FlatBuffers encoded data.
Depending on the programming language, you can use a HTTP client to fetch all data and decode the response according to each API endpoint. The following API response schema files are available:
- Weather, Marine, Ensemble, Flood and Climate API: Used for forecast and historical data
- Elevation API: Not yet available
- Geocoding API: Not yet available
Each response contains data for one location and one weather model. If multiple locations are requested, multiple ApiResponses will be returned as an array using size-prefixed
encoding (see below).
The main WeatherApiResponse
structure contains
latitude
&longitude
float: Coordinate of the weather model grid-cellelevation
float: Terrain elevation of the requested coordinatesgeneration_time_milliseconds
floatlocation_id
int64: Identifier of a locationmodel
Model: Name of weather model as an enumerationutc_offset_seconds
int32: Timezone offset from GMT time in seconds. e.g.3600
timezone
string: Timezone name likeEurope/Berlin
timezone_abbreviation
string: Abbreviation likeCET
current
VariablesWithTime: All variables requested with¤t=
daily
VariablesWithTime: All variables requested with&daily=
hourly
VariablesWithTime: All variables requested with&hourly=
minutely_15
VariablesWithTime: All variables requested with&minutely_15=
six_hourly
VariablesWithTime: All variables requested with&six_hourly=
All hourly
or daily
weather variables are grouped into the class VariablesWithTime
. It contains the start and end time as well as the interval.
Attributes:
start
int64: Unix timestamp of the first value in GMTend
int64: The last timestamp that is not included in the time-interval. Therefore one step after the last included timestep.interval
int32: The number of seconds for each step. For hourly data this is3600 seconds
and for daily data86400 seconds
.variables
[VariableWithValues]: An array of weather variables
Timestamps always use unixtime in seconds. Time is always in GMT! If you want to display local time again, you can use the attribute utc_offset_seconds
from the response structure
Each weather variable is accompanied by meta data like the name of the weather variable or unit.
Attributes:
variable
Variable: An enumeration of the weather variable. E.g.temperature
unit
Unit: Which unit is used for the result. E.g.celsius
value
float: Forcurrent
values, data is stored in this fieldvalues
[float]: Any other time-series data is stored as a floating point array herevalues_int64
[int64]: The variablessunrise
andsunset
use this field to store data as unix timestampaltitude
int16: The altitude of the given variable. E.g2
for temperature on 2 meters or10
for wind speed on 10 metersaggregation
Aggregation: The kind of aggregation for daily variables likeminimum
,mean
ormaximum
pressure_level
int16: If a weather variable in the upper atmosphere is requested, this field contains the pressure level in hectopascal. E.g.850
for 850 hPa.depth
int16: For soil variables this defined the upper limit. E.g.7
insoil_moisture_7_to_28
depth_to
int16: The lower limit. E.g.28
insoil_moisture_7_to_28
ensemble_member
int16: For ensemble data, the member of each ensemble is set here.0
is mostly the control run.
The Model
enumeration contains all available models like icon_global
or best_match
.
Depending on the programming language you will have to decode the model to a useable string. E.g. for Python
from openmeteo_sdk import Model
def model_to_name(code):
"""convert Model to name"""
for name, value in Model.Model.__dict__.items():
if value == code:
return name
return None
print(response.Model()) # 1
print(model_to_name(result.Model())) # "best_match"
The Variable
enumeration contains all available variables like temperature
or wind_speed
. Please note that the altitude is not included in the variable name. temperature_2m
is encoded as variable=temperature
and altitude=2
.
The Unit
enumeration contains all available units like celsius
or metre_per_second
.
The Aggregation
enumeration contains all aggregations for daily variables like minimum
or maximum
.
Multiple weather variables are encoded as a list. If you want to access a single variable, you will have to loop over the array and filter by variable name and altitude. Here is an example to get temperature_2m
and precipitation
.
from openmeteo_sdk.Variable import Variable
response = ...
hourly = response.Hourly()
hourly_variables = list(map(lambda i: hourly.Variables(i), range(0, hourly.VariablesLength())))
temperature_2m = next(filter(lambda x: x.Variable() == Variable.temperature and x.Altitude() == 2, hourly_variables))
precipitation = next(filter(lambda x: x.Variable() == Variable.precipitation, hourly_variables))
print(temperature_2m.ValuesAsNumpy())
print(precipitation.ValuesAsNumpy())
Depending on the variable, you only have to filter by the variable name. Filtering by altitude
is relevant if you select wind speed on multiple heights e.g. wind_speed_10m
and wind_speed_80m
.
If you select different daily aggregations, make sure to also check for the correct aggregation. Example:
from openmeteo_sdk.Variable import Variable
from openmeteo_sdk.Aggregation import Aggregation
daily = response.Daily()
daily_variables = list(map(lambda i: daily.Variables(i), range(0, daily.VariablesLength())))
temperature_2m_max = next(filter(lambda x: x.Variable() == Variable.temperature and x.Altitude() == 2 and x.Aggregation() == Aggregation.maximum, daily_variables))
temperature_2m_min = next(filter(lambda x: x.Variable() == Variable.temperature and x.Altitude() == 2 and x.Aggregation() == Aggregation.minimum, daily_variables))
print(temperature_2m_max.ValuesAsNumpy())
print(temperature_2m_min.ValuesAsNumpy())
The order of requested variables will be preserved. E.g. ¤t=temperature_2m,wind_speed_10m,weather_code
will stay exactly in this order. Therefore you could just use indices. Note: current
only returns one variable encoded into the field value
.
current = response.Current()
timestamp = current.start()
temperature_2m = current.Variables(0).value()
wind_speed_10m = current.Variables(1).value()
weather_code = current.Variables(2).value()
Data can be requested for multiple locations and multiple weather models in one API calls. E.g. &latitude=47.1,49.7&longitude=8.6,9.4
. To return multiple locations at once, multiple FlatBuffers messages are send.
To distinguish multiple messages, each message is prefixed by its length as a 32-bit integer (little endian). This is known as size-prefixed
FlatBuffer messages. Over the wire the messages look like this:
- Length: 4 byte, int32 (little endian) = 1284 byte
- Message: 1284 byte
- Length: 4 byte, int32 (little endian) = 1306 byte
- Message: 1306 byte
- ...
While decoding the response you can loop over data and process one after another. As a reference here is the Python code.
Up to 1000 locations can be requested at once. The Open-Meteo API prefetches data for all locations, but will process one location after another and "stream" the response. Therefore is it possible to decode the first message, while the next messages are still being processed on the server. This can be useful to ingest large amount of data, but is a rather complex approach. For simplicity, waiting for the entire response and then start processing data works well too.
If you would like to examine the data returned by the Open-Meteo API in binary FlatBuffers format, you can use the FlatBuffers schema compiler flatc
. This can help to understand how the API response is structured.
First, you will have to install the FlatBuffers compile. Mac: brew install flatbuffers
. Ubuntu sudo apt install flatbuffers-compiler
.
Get weather_api.fbs
from this repository.
# Make sure the URL contains `&format=flatbuffers`
wget -O data.bin https://api.open-meteo.com/v1/forecast\?latitude\=52.52\&longitude\=13.41\&daily\=weather_code,temperature_2m_max,temperature_2m_min\&timezone\=auto\&format\=flatbuffers
flatc --json --size-prefixed --raw-binary weather_api.fbs -- data.bin
cat data.json
{
latitude: 52.52,
longitude: 13.419998,
elevation: 38.0,
generation_time_milliseconds: 0.247002,
model: "best_match",
utc_offset_seconds: 3600,
timezone: "Europe/Berlin",
timezone_abbreviation: "CET",
daily: {
time: 1698620400,
time_end: 1699225200,
interval: 86400,
variables: [
{
variable: "weather_code",
unit: "wmo_code",
values: [
3.0,
80.0,
3.0,
61.0,
61.0,
61.0,
61.0
]
},
{
variable: "temperature",
unit: "celsius",
values: [
14.8455,
12.7955,
14.0455,
13.938999,
12.389,
12.3695,
14.4695
],
altitude: 2,
aggregation: "maximum"
},
{
variable: "temperature",
unit: "celsius",
values: [
11.1455,
8.1455,
7.4955,
8.488999,
8.188999,
6.389,
9.0195
],
altitude: 2,
aggregation: "minimum"
}
]
}
}
Note: The values for model
, variable
, unit
and aggregation
are encoded into enumerations which use integers instead of strings. Only timezone
and timezone_abbreviation
are actual strings that are encoded in the binary API response.
MIT