Bright Sky Radar API
The Radar API from Bright Sky — 1 operation(s) for radar.
The Radar API from Bright Sky — 1 operation(s) for radar.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/bright-sky:bright-sky-radar-api"
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Bright Sky Radar API
description: 'Bright Sky is a free and open-source weather API. It aims to provide an easy-to-use gateway to weather data that the DWD – Germany''s meteorological service – publishes on their open data server.
The public instance at `https://api.brightsky.dev/` is free-to-use for all purposes, **no API key required**! Please note that the DWD''s Terms of Use apply to all data you retrieve through the API.
> This documentation is generated from an OpenAPI specification. The current version is available from https://api.brightsky.dev/openapi.json.
## Quickstart
* Check out `/current_weather` if you want to know what the weather''s like _right now_.
* Check out `/weather` for hourly weather observations and forecasts.
* Check out `/radar` if you''re looking for a high-resolution rain radar.
* Check out `/alerts` if you''re interested in weather alerts.
... or keep reading below for some background information.
## Good to Know
* **Geographical coverage**: due to its nature as German meteorological service, the observations published by the DWD have a strong focus on Germany. The _forecasts_ cover the whole world, albeit at a much lower density outside of Germany.
* **Historical coverage**: Bright Sky serves historical data going back to January 1st, 2010. If you need data that goes further back, check out our infrastructure repository to easily set up your own instance of Bright Sky!
* **Source IDs**: Bright Sky''s _source IDs_ are a technical artifact and – unlike the DWD station IDs and WMO station IDs – have no meaning in the real world. When making requests to Bright Sky, try to avoid them and supply lat/lon or station IDs instead.
## Useful Links
* Bright Sky source code and issue tracking
* Bright Sky infrastructure configuration
* DWD Open Data landing page
* Additional explanation files for DWD Open Data, including:
* List of main observation stations
* List of additional observation stations
* List of MOSMIX stations
* List of meteorological parameters
* DWD Open Data FAQ (German)
* DWD Copyright information
## Data Sources
All data available through Bright Sky is taken or derived from data on the DWD open data server:
* **Current weather / SYNOP**:
* https://opendata.dwd.de/weather/weather_reports/synoptic/germany/json/
* **Hourly weather**:
* Historical: https://opendata.dwd.de/climate_environment/CDC/observations_germany/climate/
* Current day: https://opendata.dwd.de/weather/weather_reports/poi/
* Forecasts: https://opendata.dwd.de/weather/local_forecasts/mos/
* **Radar**:
* https://opendata.dwd.de/weather/radar/composite/rv/
* **Alerts**:
* https://opendata.dwd.de/weather/alerts/cap/COMMUNEUNION_DWD_STAT/'
contact:
name: Jakob de Maeyer
url: https://brightsky.dev/
email: jakob@brightsky.dev
license:
name: MIT License
identifier: MIT
version: 2.2.12
servers:
- url: https://api.brightsky.dev
tags:
- name: Radar
paths:
/radar:
get:
summary: Radar
description: 'Returns radar rainfall data with 1 km spatial and 5 minute temporal
resolution, including a forecast for the next two hours. Radar data is recorded on a 1200 km (North-South) x 1100 km (East-West)
grid, with each pixel representing 1 km². **That''s quite a lot of data, so
use `lat`/`lon` or `bbox` whenever you can (see below).** Past radar
records are kept for six hours. Bright Sky can return the data in a few formats. Use the default
`compressed` format if possible – this''ll get you the fastest response
times by far and reduce load on the server. If you have a small-ish
bounding box (e.g. 250 x 250 pixels), using the `plain` format should be
fine. ### Quickstart
This request will get you radar data near Münster, reaching 200 km to the
East/West/North/South, as a two-dimensional grid of integers:
`https://api.brightsky.dev/radar?lat=52&lon=7.6&format=plain`
### Content
* The grid is a polar stereographic projection of Germany and the regions
bordering it. This is different from the mercator projection used for
most consumer-facing maps like OpenStreetMap or Google Maps, and
overlaying the radar data onto such a map without conversion
(reprojection) will be inaccurate! Check out our radar
demo for an example of correctly
reprojecting the radar data using OpenLayers. Alternatively, take a look
at the `dwd:RV-Produkt` layer on the DWD''s open
GeoServer
for ready-made tiles you can overlay onto a map. * The proj-string for the
grid projection is `+proj=stere +lat_0=90 +lat_ts=60 +lon_0=10 +a=6378137
+b=6356752.3142451802 +no_defs +x_0=543196.83521776402
+y_0=3622588.8619310018`. The radar pixels range from `-500` (left) to
`1099500` (right) on the x-axis, and from `500` (top) to `-1199500`
(bottom) on the y-axis, each radar pixel a size of `1000x1000` (1 km²). * The DWD data does not cover the whole grid! Many areas near the edges
will always be `0`. * Values represent 0.01 mm / 5 min. I.e., if a pixel has a value of `45`,
then 0.45 mm of precipitation fell in the corresponding square kilometer
in the past five minutes. * The four corners of the grid are as follows:
* Northwest: Latitude `55.86208711`, Longitude `1.463301510`
* Northeast: Latitude `55.84543856`, Longitude `18.73161645`
* Southeast: Latitude `45.68460578`, Longitude `16.58086935`
* Southwest: Latitude `45.69642538`, Longitude `3.566994635`
You can find details and more information in the DWD''s `RV product info`
(German
only). Below is an example visualization of the rainfall radar data taken from
this document, using the correct projection and showing the radar coverage:
!image
### Code examples
> The radar data is quite big (naively unpacking the default 25-frames
> response into Python integer arrays will eat roughly 125 MB of memory),
> so use `bbox` whenever you can. #### `compressed` format
With Javascript using `pako`:
```js
fetch(
''https://api.brightsky.dev/radar''
).then((resp) => resp.json()
).then((respData) => {
const raw = respData.radar[0].precipitation_5;
const compressed = Uint8Array.from(atob(raw), c => c.charCodeAt(0));
const rawBytes = pako.inflate(compressed).buffer;
const precipitation = new Uint16Array(rawBytes);
});
```
With Python using `numpy`:
```python
import base64
import zlib
import numpy as np
import requests
resp = requests.get(''https://api.brightsky.dev/radar'')
raw = resp.json()[''radar''][0][''precipitation_5'']
raw_bytes = zlib.decompress(base64.b64decode(raw))
data = np.frombuffer(
raw_bytes,
dtype=''i2'',
).reshape(
# Adjust `1200` and `1100` to the height/width of your bbox
(1200, 1100),
)
```
With Python using the standard library''s `array`:
```python
import array
# [... load raw_bytes as above ...]
data = array.array(''H'')
data.frombytes(raw_bytes)
data = [
# Adjust `1200` and `1100` to the height/width of your bbox
data[row*1100:(row+1)*1100]
for row in range(1200)
]
```
Simple plot using `matplotlib`:
```python
import matplotlib.pyplot as plt
# [...'
operationId: getRadar
parameters:
- name: bbox
in: query
required: false
schema:
type: array
items:
type: integer
description: Bounding box (top, left, bottom, right) **in pixels**, edges are inclusive. (_Defaults to full 1200x1100 grid._)
examples:
- 100,100,300,300
title: Bbox
description: Bounding box (top, left, bottom, right) **in pixels**, edges are inclusive. (_Defaults to full 1200x1100 grid._)
- name: distance
in: query
required: false
schema:
type: integer
description: Alternative way to set a bounding box, must be used together with `lat` and `lon`. Data will reach `distance` meters to each side of this location, but is possibly cut off at the edges of the radar grid.
examples:
- 100000
default: 200000
title: Distance
description: Alternative way to set a bounding box, must be used together with `lat` and `lon`. Data will reach `distance` meters to each side of this location, but is possibly cut off at the edges of the radar grid.
- name: lat
in: query
required: false
schema:
type: number
maximum: 90
minimum: -90
description: Latitude in decimal degrees.
examples:
- 52.52
- 51.55
title: Lat
description: Latitude in decimal degrees.
- name: lon
in: query
required: false
schema:
type: number
maximum: 180
minimum: -180
description: Longitude in decimal degrees.
examples:
- 13.4
- 9.9
title: Lon
description: Longitude in decimal degrees.
- name: date
in: query
required: false
schema:
type: string
format: date-time
description: Timestamp of first record to retrieve, in ISO 8601 format. May contain time and/or UTC offset. (_Defaults to 1 hour before latest measurement._)
examples:
- '2023-08-07'
- 2023-08-07T19:00+02:00
title: Date
description: Timestamp of first record to retrieve, in ISO 8601 format. May contain time and/or UTC offset. (_Defaults to 1 hour before latest measurement._)
- name: last_date
in: query
required: false
schema:
type: string
format: date-time
description: Timestamp of last record to retrieve, in ISO 8601 format. May contain time and/or UTC offset. (_Defaults to 2 hours after `date`._)
examples:
- '2023-08-08'
- 2023-08-07T23:00+02:00
title: Last Date
description: Timestamp of last record to retrieve, in ISO 8601 format. May contain time and/or UTC offset. (_Defaults to 2 hours after `date`._)
- name: format
in: query
required: false
schema:
enum:
- compressed
- bytes
- plain
type: string
description: "\nDetermines how the precipitation data is encoded into the `precipitation_5` field:\n* `compressed`: base64-encoded, zlib-compressed bytestring of 2-byte integers\n* `bytes`: base64-encoded bytestring of 2-byte integers\n* `plain`: Nested array of integers\n "
default: compressed
title: Format
description: "\nDetermines how the precipitation data is encoded into the `precipitation_5` field:\n* `compressed`: base64-encoded, zlib-compressed bytestring of 2-byte integers\n* `bytes`: base64-encoded bytestring of 2-byte integers\n* `plain`: Nested array of integers\n "
- name: tz
in: query
required: false
schema:
type: string
description: Timezone in which record timestamps will be presented, as <a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones">tz database name</a>. Will also be used as timezone when parsing `date` and `last_date`, unless these have explicit UTC offsets. If omitted but `date` has an explicit UTC offset, that offset will be used as timezone. Otherwise will default to UTC.
examples:
- Europe/Berlin
- Australia/Darwin
- Etc/UTC
title: Tz
description: Timezone in which record timestamps will be presented, as <a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones">tz database name</a>. Will also be used as timezone when parsing `date` and `last_date`, unless these have explicit UTC offsets. If omitted but `date` has an explicit UTC offset, that offset will be used as timezone. Otherwise will default to UTC.
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/RadarResponse'
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/NotFoundResponse'
description: Not Found
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
tags:
- Radar
components:
schemas:
RadarRecord:
properties:
timestamp:
type: string
format: date-time
title: Timestamp
description: ISO 8601-formatted timestamp of this radar record
examples:
- '2023-08-07T08:00:00+00:00'
source:
type: string
title: Source
description: Unique identifier for DWD radar product source of this radar record
examples:
- RADOLAN::RV::2023-08-08T11:45:00+00:00
precipitation_5:
type: string
title: Precipitation 5
description: Pixelwise 5-minute precipitation data, in units of 0.01 mm / 5 min. Depending on the `format` parameter, this field contains either a two-dimensional array of integers (`plain`), or a base64 string (`bytes` or `compressed`).
examples:
- eF5jGAWjYBTQEQAAA3IAAQ==
type: object
title: RadarRecord
NotFoundResponse:
properties:
detail:
type: string
title: Detail
default: Error details
type: object
title: NotFoundResponse
HTTPValidationError:
properties:
detail:
items:
$ref: '#/components/schemas/ValidationError'
type: array
title: Detail
type: object
title: HTTPValidationError
RadarResponse:
properties:
radar:
items:
$ref: '#/components/schemas/RadarRecord'
type: array
title: Radar
geometry:
additionalProperties: true
type: object
title: Geometry
description: GeoJSON-formatted bounding box of returned radar data, i.e. lat/lon coordinates of the four corners.
examples:
- coordinates:
- - 7.44365
- 52.08712
- - 7.45668
- 51.90644
- - 7.7487
- 51.914
- - 7.73716
- 52.09473
type: Polygon
bbox:
items:
type: integer
type: array
title: Bbox
description: Bounding box (top, left, bottom, right) calculated from the supplied position and distance. Only returned if you supplied `lat` and `lon`.
examples:
- - 100
- 100
- 300
- 300
nullable: true
latlon_position:
additionalProperties: true
type: object
title: Latlon Position
description: Exact x-y-position of the supplied position. Only returned if you supplied `lat` and `lon`.
examples:
- x: 10.244
y: 10.088
nullable: true
type: object
title: RadarResponse
ValidationError:
properties:
loc:
items:
anyOf:
- type: string
- type: integer
type: array
title: Location
msg:
type: string
title: Message
type:
type: string
title: Error Type
input:
title: Input
ctx:
type: object
title: Context
type: object
required:
- loc
- msg
- type
title: ValidationError