Skip to main content

dwdopen

Python library to access DWD Open Data numerical weather prediction (NWP) data: discover what data is currently offered, define what you want, and download it.

Still in "pre-alpha", not everything works yet. See Not yet implemented.

Install

Requires Python 3.11 or newer.

pip install dwdopen

Quickstart

from dwdopen import DWD

with DWD() as dwd:
    icon_eu = dwd.nwp.model("icon-eu")

    query = icon_eu.select(parameters=["T_2M", "PMSL"], steps="6h")
    query.download("forecast.grib2")

Discovery

dwd.nwp.models()                    # every model DWD currently publishes
icon_eu.parameters()                # every parameter of one model
icon_eu.parameter("T").level_types  # (pressure (100), model (150))
icon_eu.levels("T", "pressure")     # available level values

Selecting

Forecast steps

Steps are durations, ICON-D2 publishes precipitation every 15 minutes and ICON-D2-RUC every 5.

from dwdopen import Between, Every, hours, minutes

steps="6h"                        # exactly this step
steps=["0h", "3h", "6h"]          # exactly these
steps=Every("0h", "48h", "3h")    # interval, inclusive at both ends
steps=Between("0h", "48h")        # whatever exists in the interval
steps="all"                       # everything published

steps=hours(0, 6, 12, 18)         # plain numbers, if that is what you have
steps=hours(range(0, 121, 3))     # or any iterable of them
steps=minutes(0, 15, 30)          # for the sub-hourly models

hours() and minutes() turn a single number into a single duration, so they compose with the others too: Every(hours(0), hours(48), hours(3)).

Every names exact steps, so a missing one makes the request incomplete. Between and "all" ask for whatever is there and can never be incomplete.

Note that DWD publishes data incrementally on the server, so a run might just be halfway available. If you use Between, you might just get what's already available, not the full data.

Ensemble members

The -eps models publish each member separately. Members are plain integers; how many there are differs per model (40 for ICON-EPS and ICON-EU-EPS, 20 for ICON-D2-EPS, 10 for ICON-ART-EPS):

eps.select(parameters="T_2M", members=[1, 2, 5])
eps.select(parameters="T_2M", members=Between(1, 10))
eps.select(parameters="T_2M")                       # every member

Leaving members out takes all of them, the same as levels and steps.

Vertical levels

icon_eu.select(parameters="T", level_type="pressure", levels=[850, 500])
icon_eu.select(parameters="T", level_type="model", levels=Between(60, 74))
icon_eu.select(parameters="T_SO", level_type="soil", levels="all")

level_type may be left out only while the selection is unambiguous. T is available on both pressure and model levels, so omitting it raises AmbiguousSelectionError rather than guessing. A 2-D field such as T_2M needs no level type at all. Time-invariant fields need no level type either. These are published under every run with a single step. HHL is the exception, being model half-level heights:

icon_d2.select(parameters="HSURF", steps="0h")                      # no level type
icon_d2.select(parameters="HHL", level_type="model", levels="all")

Investigate before you download

resolve() freezes a query against one run and hands back a plan you can inspect before any download happens:

plan = icon_eu.select(parameters="U", level_type="pressure").resolve()
print(plan)
# ResolvedRequest(run=2026-09-23T06:00:00+00:00, 1860 assets, 1.5 GB, U,
#                 on pressure (100), 20 levels, steps 0h..120h)

print(plan.assets[0])
# Asset(U, 50 hPa, 0h, 723.4 KB)

plan.download("u.grib2")

A plan never switches to a newer run later, so what you inspected is what you get.

Downloading

query.download("forecast.grib2")                    # one combined file
query.download("members/", combine="member")        # one file per ensemble member
query.download("forecast/", combine="none")         # one file per message
query.download("f.grib2", temp_dir="/scratch")      # partial downloads before combining elsewhere

combine="all" concatenates the messages into a single GRIB2 file. You can also provide just a directory in this case and the name is generated automatically.

plan = query.resolve()
plan.suggested_name()            # 'icon-eu_2026-09-24T0600_PMSL+T_2M_0h-24h.grib2'
plan.download("/home/weather/")   # writes that name into the directory

Downloads run concurrently, are written to a temporary name and renamed into place, so a partial file is never mistaken for a finished one. Several processes may write the same directory at once. Already downloaded files are skipped. DownloadResult.assets_skipped says how many were already there, which is worth checking in a scheduled job.

Logging

The library logs through the standard dwdopen logger. It never prompts or reads from stdin as the library is meant to run unattended.

import logging
logging.basicConfig(level=logging.INFO)

INFO reports what is about to be downloaded and how large it is. WARNING covers retries and mixed level types.

Not yet implemented

  • combine="parameter".
  • Listing cache. Every call re-reads the catalogue today.
  • Feedback of download progress (bar, text, visual?)
  • ICON-ART wavelengths (the wvl1 segment).
  • A command-line interface.
  • Automatic parameter choice for Model.latest_run(), which needs parameter= at the moment.

License

MIT. See LICENSE.

Forecast data itself is provided by Deutscher Wetterdienst (DWD) under its own terms of use.

Metadata

Release files for dwdopen 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dwdopen 0.2.2
File Size Uploaded Provenance Actions
dwdopen-0.2.2.tar.gz 54.8 kB With provenance Details for dwdopen-0.2.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for dwdopen 0.2.2
File Interpreter ABI Platform Actions
dwdopen-0.2.2-py3-none-any.whl Python 3 none any Details for dwdopen-0.2.2-py3-none-any.whl

Total release size: 98.3 kB

Release files / dwdopen-0.2.2.tar.gz

Download URL dwdopen-0.2.2.tar.gz
Size 54.8 kB
Tags Source
SHA-256 checksum
How to use checksums
150c946f52a509a4533ea4dbbf85cf6d77503673d3241052be1284518089bdbb
BLAKE2b-256 checksum
How to use checksums
d38fc18a9fd9eb70b4509f5c05c8dc7b18f42f49ccec1c171ddac31d4cb05bbf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release files / dwdopen-0.2.2-py3-none-any.whl

Download URL dwdopen-0.2.2-py3-none-any.whl
Size 43.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e93987e4d1699bdf2a7ad0f01415bb115fa9da651694aba5959214f416e2d070
BLAKE2b-256 checksum
How to use checksums
0fdffaf71278b38f50a0c4cc51bc9a9c0887f79736f95e40b4a9da710d7b49fa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Security for dwdopen 0.2.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for dwdopen-0.2.2.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page