Trinkwasser Open Data: CSV, API und Zitierhinweis
Wie kommen Sie an die Daten, und wie zitieren Sie genau den Stand, mit dem Sie gearbeitet haben?
Dateien
- trinkwasser-messwerte.csv: Langfassung, eine Zeile je Wert, Stadt und Wasser (Komma, Dezimalpunkt, UTF-8). Grundlage aller Tabellen dieses Bereichs.
- trinkwasser-messwerte-excel.csv: dieselben Zeilen für deutsches Excel (Semikolon, Dezimalkomma). Andere Bytes, daher eine andere Prüfsumme.
- trinkwasser-daten.json: alle Städte mit ihren Wässern und Messwerten, verschachtelt.
- datenstand.json: Datenstand-Kennung, SHA-256 jeder Datei und die ausgewerteten Prüfberichte mit ihren Prüfsummen.
Alle Dateien und Druckfassungen stehen im Downloadcenter.
Datenstand und Prüfsumme prüfen
Das jüngste Messdatum allein identifiziert eine Datenversion nicht: Neue Berichte können ältere Messdaten enthalten. Die Prüfsumme schon. Die Tabellen dieses Bereichs beruhen auf der CSV mit der Prüfsumme 33cb9bd2af89 (die ersten 12 Zeichen von SHA-256, Datenstand-Kennung 2026-10-07-291de1d0). So prüfen Sie Ihre Datei:
sha256sum trinkwasser-messwerte.csv
Stimmen die ersten 12 Zeichen nicht überein, ist Ihre Datei ein anderer Stand. Dann können Ihre Zahlen von denen auf diesen Seiten abweichen, ohne dass einer von beiden falsch gerechnet hat.
Schnittstelle (API) und MCP
Ohne Anmeldung, JSON. Für Lehre und Forschung besonders nützlich:
/api/v1/gaps?substance={schluessel}: Lücken-Register: wie viele Orte einen Stoff nennen und wie viele nicht/api/v1/changes?city={slug}: Werte zweier aufeinanderfolgender Prüfberichte desselben Wassers, mit beiden Quellen/api/v1/evidence?city={slug}: Jeder Wert eines Orts als Beleg-Objekt mit Quelle, Messdatum und Grenzwert
Alle Endpunkte stehen in der OpenAPI-Beschreibung und im Downloadcenter. KI-Assistenten können die Werte über einen MCP-Server abfragen. Die API liefert den jeweils aktuellen Stand der Datenbank; er kann neuer sein als die CSV, auf der diese Seite beruht.
Spaltenwörterbuch
| Spalte | Typ | Einheit | Bedeutung |
|---|---|---|---|
stadt | Text | – | Name der Stadt, wie auf der Stadtseite |
stadt_slug | Text | – | Kennung der Stadt in unseren Adressen (/trinkwasser/{slug}/) |
bundesland | Text | – | Bundesland |
landkreis | Text | – | Landkreis bzw. kreisfreie Stadt |
breitengrad | Zahl | Grad (WGS 84) | Lage des Stadtmittelpunkts (WGS 84), nur zur Einordnung, keine Messstelle |
laengengrad | Zahl | Grad (WGS 84) | Lage des Stadtmittelpunkts (WGS 84) |
versorger | Text | – | Wasserversorger hinter den Werten |
wasser | Text | – | Nur bei Städten mit mehreren Wässern: Name des Wassers laut Versorger, sonst leer |
wasser_anteil_adressen_prozent | Zahl | Prozent | Nur bei mehreren Wässern: Anteil der Adressen der Stadt, die dieses Wasser bekommen (Adressabfrage des Versorgers) |
parameter_schluessel | Text | – | Maschinenlesbarer Schlüssel, z. B. nitrat, haerte, pfas |
parameter | Text | – | Bezeichnung des Parameters |
wert | Zahl | Spalte einheit | Gemessener Wert; leer, wenn er unter der Bestimmungsgrenze lag |
einheit | Text | – | Einheit von Wert, Bestimmungsgrenze und Grenzwerten |
unter_bestimmungsgrenze | true/false | – | true/ja, wenn der Stoff nicht quantifizierbar war |
bestimmungsgrenze | Zahl | Spalte einheit | Bestimmungsgrenze des Labors, wenn der Wert darunter lag |
grenzwert_trinkwv | Zahl | Spalte einheit | Geltender Grenzwert der Trinkwasserverordnung (bei pH die Obergrenze, bei Mikrobiologie 0); leer, wenn es keinen gibt (z. B. Härte) |
grenzwert_trinkwv_untere | Zahl | Spalte einheit | Untere Grenze, nur beim pH-Wert (6,5) |
grenzwert_kuenftig | Zahl | Spalte einheit | Künftig geltender Wert, z. B. Blei 0,005 mg/L und Summe PFAS-4 ab 12.01.2028 |
grenzwert_kuenftig_ab | Datum (ISO 8601) | – | Datum, ab dem der künftige Wert gilt |
messdatum | Datum (ISO 8601) | – | Datum der Probenahme bzw. Ende des Mittelungszeitraums laut Bericht – nur so genau, wie der Bericht es angibt: 2026-03-02, 2026-03 (nur Monat) oder 2025 (nur Jahr, z. B. Jahresmittelwerte) |
messdatum_genauigkeit | Text | – | tag, monat oder jahr – wie genau der Bericht das Datum angibt |
pruefstatus | Text | – | verified, partially_verified, unverified, outdated – Prüfstand des Werts in unserer Datenbank |
quelle_herausgeber | Text | – | Herausgeber des Prüfberichts |
quelle_titel | Text | – | Titel des Prüfberichts |
quelle_url | URL | – | Link auf den Prüfbericht beim Versorger |
seite_url | URL | – | Unsere Stadtseite mit Einordnung und Hinweisen |
Lizenz
Daten und Texte stehen unter Creative Commons Namensnennung 4.0 International (CC BY 4.0). Namensnennung: „Trinkwassermonitor (trinkwassermonitor.ink), Werte aus den Prüfberichten der Wasserversorger“.
Zitierhinweis
- Zitieren Sie den Datensatz mit Datenstand und Abrufdatum.
- Zitieren Sie einzelne Messwerte immer mit Quelle, Messdatum und URL des Prüfberichts.
So bleiben die Auswertung von Trinkwassermonitor und die Originalquelle getrennt: Für einen einzelnen Wert nennen Sie den Prüfbericht aus den Spalten quelle_herausgeber, quelle_titel und quelle_url sowie messdatum.
Vorschlag für den Datensatz, mit dem Stand dieser Seite:
Trinkwassermonitor: Geprüfte Trinkwasserwerte (Datensatz trinkwasser-messwerte.csv). Lizenz CC BY 4.0. Datenstand 07.10.2026, Kennung 2026-10-07-291de1d0, Prüfsumme SHA-256 33cb9bd2af89. https://trinkwassermonitor.ink/downloads/daten/trinkwasser-messwerte.csv. Abruf: vom Zitierenden einzutragen.
Dieser Stand ist noch nicht bei Zenodo archiviert und hat daher keine eigene Versions-DOI. Zuletzt archiviert wurde der Stand 2026-09-14-ea23f366 (doi:10.5281/zenodo.23670464). Zitieren Sie diesen Stand mit Kennung und Prüfsumme. Die Serien-DOI doi:10.5281/zenodo.23451788 zeigt immer auf die neueste archivierte Fassung.
Codebeispiele
Die Beispiele zählen für den Stoff fluorid (Fluorid) die Zeilen unter der Bestimmungsgrenze, wie in Fall 1. Der Stoff ist nach einer festen Regel gewählt, nicht nach Bedeutung: Er hat einen Grenzwert, eine Einheit und zwischen einem Viertel und drei Vierteln Zeilen unter der Bestimmungsgrenze. Der Code wird auf dieser Seite nur angezeigt, nicht ausgeführt.
Python (pandas, requests)
CSV laden und Zeilen unter der Bestimmungsgrenze zählen
import pandas as pd
URL = "https://trinkwassermonitor.ink/downloads/daten/trinkwasser-messwerte.csv"
df = pd.read_csv(URL, dtype=str, keep_default_na=False)
stoff = df[df["parameter_schluessel"] == "fluorid"]
n = len(stoff)
unter_bg = (stoff["unter_bestimmungsgrenze"] == "true").sum()
print(f"n = {n}, unter Bestimmungsgrenze: {unter_bg} ({100 * unter_bg / n:.0f} %)")
Prüfsumme der heruntergeladenen Datei mit der Seite vergleichen
import hashlib
import requests
daten = requests.get("https://trinkwassermonitor.ink/downloads/daten/trinkwasser-messwerte.csv", timeout=60).content
print(hashlib.sha256(daten).hexdigest()[:12]) # mit „Prüfsumme der CSV“ auf dieser Seite vergleichen
Lücken-Register über die API abfragen
import requests
antwort = requests.get("https://trinkwassermonitor.ink/api/v1/gaps", params={"substance": "fluorid"}, timeout=30)
antwort.raise_for_status()
print(antwort.json())
R (readr, httr2, jsonlite)
CSV laden und Zeilen unter der Bestimmungsgrenze zählen
library(readr)
url <- "https://trinkwassermonitor.ink/downloads/daten/trinkwasser-messwerte.csv"
df <- read_csv(url, col_types = cols(.default = col_character()), na = character())
stoff <- df[df$parameter_schluessel == "fluorid", ]
n <- nrow(stoff)
unter_bg <- sum(stoff$unter_bestimmungsgrenze == "true")
cat("n =", n, "- unter Bestimmungsgrenze:", unter_bg, "(", round(100 * unter_bg / n), "% )\n")
Lücken-Register über die API abfragen
library(httr2)
library(jsonlite)
antwort <- request("https://trinkwassermonitor.ink/api/v1/gaps") |>
req_url_query(substance = "fluorid") |>
req_perform()
luecken <- fromJSON(resp_body_string(antwort))
str(luecken)