Bright Sky Radar API

The Radar API from Bright Sky — 1 operation(s) for radar.

Operations 1

GET /radar Radar #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • 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.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/bright-sky:bright-sky-radar-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

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 Specification

bright-sky-radar-api-openapi.yml Raw ↑
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