PublicData – kostenlose CSV-Datensätze für DACH und international
PublicData ist meine offene Sammlung von Referenzdatensätzen als CSV-Dateien: Postleitzahlen, Gemeinden, Landkreise, Vorwahlen, Kfz-Kennzeichen und Einwohnerzahlen für Deutschland, Österreich und die Schweiz, dazu internationale Stammdaten wie Länder-, Währungs- und Sprachcodes.
Alle Dateien liegen in meinem öffentlichen Repository und sind kostenfrei, ohne Anmeldung und ohne API-Key abrufbar:
code.beautifulmachines.dev/jakoubek/publicdata
Warum diese Sammlung?
Fast jedes Datenprojekt braucht irgendwann dieselben Stammdaten. Eine Kundenliste soll nach Bundesland ausgewertet werden, Adressen sollen gegen gültige Postleitzahlen geprüft werden, ein Report soll Umsätze pro Landkreis zeigen.
Die Daten sind amtlich und frei verfügbar, aber sie liegen bei Destatis, der Statistik Austria, dem BFS oder der Bundesnetzagentur in Formaten, die für die direkte Weiterverarbeitung ungeeignet sind: Excel-Dateien mit Kopfzeilen über mehrere Ebenen, Fußnoten mitten in den Daten, wechselnde Spaltennamen, mal Semikolon, mal Tabulator, mal Windows-1252.
Diese Aufbereitung habe ich für meine eigenen Projekte ohnehin gemacht. Statt sie in jedem Projekt zu wiederholen, liegt sie jetzt öffentlich, in einem einheitlichen Format vor:
- UTF-8 kodiert
- Komma als Trennzeichen
- LF als Zeilenende
- Eine Kopfzeile mit stabilen, sprechenden Spaltennamen
- Führende Nullen erhalten (
08bleibt08und wird nicht zu8) - Über gemeinsame Schlüssel wie den Amtlichen Gemeindeschlüssel verknüpfbar
Die Datensätze
International
| Datei | Inhalt | Zeilen |
|---|---|---|
countries.csv |
Länder mit ISO-3166-1-Codes (alpha-2, alpha-3, numerisch), Region und Subregion | 249 |
currencies.csv |
Währungen nach ISO 4217 mit Code, Name und Dezimalstellen | 178 |
languages.csv |
Sprachen nach ISO 639 | 486 |
calling_codes.csv |
Internationale Telefonvorwahlen, verknüpft mit dem Ländercode | 248 |
Deutschland
| Datei | Inhalt | Zeilen |
|---|---|---|
bundeslaender_de.csv |
Bundesländer mit AGS- und ISO-Code | 16 |
landkreise_de.csv |
Landkreise und kreisfreie Städte | 400 |
gemeinden_de.csv |
Gemeinden, verknüpft mit Landkreis und Bundesland | 10.943 |
postleitzahlen_de.csv |
Postleitzahlen mit Ort, Bundesland und AGS | 8.293 |
vorwahlen_de.csv |
Telefonvorwahlen mit Ort | 5.200 |
kfz_kennzeichen_de.csv |
Kfz-Unterscheidungszeichen | 769 |
einwohner_de.csv |
Bevölkerung, Fläche und Dichte je Gemeinde (Stand 31.12.2024) | 10.943 |
Österreich
| Datei | Inhalt | Zeilen |
|---|---|---|
bundeslaender_at.csv |
Bundesländer mit ÖSTAT- und ISO-Code | 9 |
gemeinden_at.csv |
Gemeinden mit Gemeindekennziffer | 2.092 |
postleitzahlen_at.csv |
Postleitzahlen mit Ort und Bundesland | 2.501 |
vorwahlen_at.csv |
Telefonvorwahlen mit Ort | 1.022 |
einwohner_at.csv |
Bevölkerung je Gemeinde (Stand 1.1.2026) | 2.092 |
Schweiz
| Datei | Inhalt | Zeilen |
|---|---|---|
kantone_ch.csv |
Kantone mit Abkürzung und ISO-Code | 26 |
gemeinden_ch.csv |
Gemeinden mit BFS-Nummer, Bezirk und Kanton | 2.131 |
postleitzahlen_ch.csv |
Postleitzahlen mit Ort und Kanton | 3.362 |
vorwahlen_ch.csv |
Geografische Vorwahlgebiete | 20 |
einwohner_ch.csv |
Ständige Wohnbevölkerung je Gemeinde (Stand 31.12.2024) | 2.131 |
Direkt einlesen mit DuckDB
DuckDB ist eine analytische Datenbank, die vollständig im eigenen, lokalen Prozess läuft: kein Server und keine Installation im klassischen Sinn. Für genau solche Aufgaben ist sie ideal: CSV-Dateien lesen, verknüpfen, auswerten und exportieren.
Dabei liest DuckDB CSV-Dateien direkt über HTTPS. Sie müssen nichts herunterladen.
SELECT * FROM read_csv(
'https://code.beautifulmachines.dev/jakoubek/publicdata/raw/branch/main/bundeslaender_de.csv',
header = true,
all_varchar = true
);
Der Parameter all_varchar = true ist wichtig. Er verhindert, dass DuckDB Schlüsselfelder als Zahlen interpretiert und dabei führende Nullen wegwirft. Aus dem AGS-Code 08 für Baden-Württemberg würde sonst eine 8, und der Join gegen Ihre eigenen Daten liefert keinen Treffer mehr.
Basis-URL einmal setzen
Damit die folgenden Beispiele lesbar bleiben, lege ich die Basis-URL als Variable ab:
SET VARIABLE base =
'https://code.beautifulmachines.dev/jakoubek/publicdata/raw/branch/main/';
Als Tabelle übernehmen
Wenn Sie mehrfach mit den Daten arbeiten, laden Sie sie einmal in eine persistente Tabelle:
CREATE TABLE postleitzahlen AS
SELECT * FROM read_csv(
getvariable('base') || 'postleitzahlen_de.csv',
header = true,
all_varchar = true
);
Die Datei enthält die Spalten plz, ort, bundesland und ags_code.
Mehrere Datensätze verknüpfen
Die deutschen Datensätze sind über den Amtlichen Gemeindeschlüssel hierarchisch verbunden: Gemeinde, Landkreis, Bundesland.
SELECT
b.name AS bundesland,
count(*) AS anzahl_gemeinden
FROM read_csv(getvariable('base') || 'gemeinden_de.csv',
header = true, all_varchar = true) g
JOIN read_csv(getvariable('base') || 'landkreise_de.csv',
header = true, all_varchar = true) l
ON g.kreis_code = l.ags_code
JOIN read_csv(getvariable('base') || 'bundeslaender_de.csv',
header = true, all_varchar = true) b
ON l.state_code = b.ags_code
GROUP BY b.name
ORDER BY anzahl_gemeinden DESC;
Die Einwohnerdaten hängen ebenfalls am AGS-Code, hier auf Gemeindeebene. So kommen Sie in einer Abfrage zu den zehn größten Städten Deutschlands:
SELECT
g.name,
g.bundesland,
e.population::bigint AS einwohner
FROM read_csv(getvariable('base') || 'einwohner_de.csv',
header = true, all_varchar = true) e
JOIN read_csv(getvariable('base') || 'gemeinden_de.csv',
header = true, all_varchar = true) g
ON e.ags_code = g.ags_code
ORDER BY einwohner DESC
LIMIT 10;
Ihre eigenen Daten anreichern
Der häufigste Anwendungsfall: eine eigene Datei mit Kundenadressen um die Region ergänzen.
SELECT
k.kundennummer,
k.plz,
p.ort,
p.bundesland
FROM read_csv('kunden.csv', header = true, all_varchar = true) k
LEFT JOIN postleitzahlen p ON k.plz = p.plz;
Zeilen ohne Treffer zeigen sofort, wo Ihre Stammdaten fehlerhaft sind: Tippfehler in Postleitzahlen, veraltete Orte, vertauschte Felder.
Ergebnisse exportieren
DuckDB schreibt in nahezu jedes Format:
COPY (SELECT * FROM postleitzahlen)
TO 'postleitzahlen.parquet' (FORMAT parquet);
COPY (SELECT * FROM postleitzahlen)
TO 'postleitzahlen.json' (FORMAT json, ARRAY true);
Direkt in Ihre Datenbank
Mit der Postgres-Erweiterung schreiben Sie die Daten in einem Schritt in Ihre bestehende PostgreSQL-Datenbank. Sie benötigen dafür keine zusätzliche Zwischendatei und kein Import-Skript:
INSTALL postgres;
LOAD postgres;
ATTACH 'dbname=meinedb user=app host=localhost' AS pg (TYPE postgres);
CREATE TABLE pg.postleitzahlen AS
SELECT * FROM read_csv(
'https://code.beautifulmachines.dev/jakoubek/publicdata/raw/branch/main/postleitzahlen_de.csv',
header = true,
all_varchar = true
);
Ohne SQL-Datei, direkt in der Shell
duckdb -c "SELECT * FROM read_csv('https://code.beautifulmachines.dev/jakoubek/publicdata/raw/branch/main/kantone_ch.csv', header = true, all_varchar = true)"
Mit Python
Auch ohne DuckDB genügt eine Zeile:
import pandas as pd
url = "https://code.beautifulmachines.dev/jakoubek/publicdata/raw/branch/main/countries.csv"
countries = pd.read_csv(url, dtype=str)
dtype=str erfüllt hier denselben Zweck wie all_varchar in DuckDB.
Nutzen für Unternehmen
Typische Situationen aus meinen Projekten:
Auswertungen bekommen eine geografische Dimension. Umsatz pro Postleitzahl ergibt eine Liste mit 8.293 Zeilen. Für die Auswertung nach Bundesland oder Landkreis fehlt nur die Zuordnungstabelle.
Datenqualität wird prüfbar. Ein Join gegen die Postleitzahlen-Liste macht in Sekunden sichtbar, welche Adressen in Ihrem CRM- oder ERP-System fehlerhaft sind.
Auswahllisten und Formulare werden konsistent. Länder- und Währungscodes nach ISO-Norm statt frei getippter Werte zahlen sich spätestens bei der ersten Schnittstelle zu einem anderen System aus.
Gebietszuschnitt und Tourenplanung bekommen eine Grundlage. Vertriebsgebiete, Zustellbezirke, Servicegebiete: Jede Gebietslogik beginnt mit der Zuordnung von Postleitzahl zu Gemeinde und Landkreis.
Kennzahlen werden vergleichbar. Absolute Zahlen pro Region sagen wenig, solange die Regionen unterschiedlich groß sind. Mit der Einwohnerzahl als Bezugsgröße rechnen Sie Verkaufszahlen pro Kopf und stellen Regionen sinnvoll nebeneinander.
Stammdaten müssen nicht selbst gepflegt werden. Gemeinden fusionieren, Postleitzahlen kommen hinzu, Einwohnerzahlen werden fortgeschrieben. Wenn die Daten über eine URL kommen, ist die Aktualisierung ein erneuter Aufruf und kein Ticket.
Ein Data-Warehouse ist dafür nicht nötig. DuckDB läuft auf einem Notebook, in einem Container oder in einem Cron-Job. Für Datenmengen dieser Größenordnung braucht es keine eigene Server-Infrastruktur.
Lizenz und Quellen
Die Datensätze stehen unter der Creative-Commons-Lizenz Attribution 4.0 International (CC BY 4.0). Sie dürfen sie kopieren, weitergeben, verändern und auch kommerziell nutzen, in internen Auswertungen ebenso wie in einem Produkt, das Sie verkaufen. Eine Rückfrage bei mir ist nicht nötig, eine Lizenzgebühr fällt nicht an.
Die einzige Bedingung ist die Namensnennung.
So geben Sie die Quelle an
Ein Satz genügt, etwa im Quellenverzeichnis eines Reports, auf einer Impressumsseite oder als Kommentar im Code:
Datenbasis: PublicData von Oliver Jakoubek, lizenziert unter CC BY 4.0, https://www.jakoubek.net/publicdata/
Zum Kopieren für Ihre Dokumentation oder Ihre Website:
Datenbasis: [PublicData](https://www.jakoubek.net/publicdata/) von Oliver Jakoubek, lizenziert unter [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/deed.de).
In einer Anwendung reicht die Nennung an der Stelle, an der Sie ohnehin Ihre Drittanbieter-Lizenzen aufführen. In einem Diagramm genügt eine Quellenzeile unter der Grafik.
Die zugrunde liegenden Daten stammen aus amtlichen und offenen Quellen, unter anderem von Destatis, der Statistik Austria, dem Bundesamt für Statistik (BFS), der Bundesnetzagentur und GeoNames. Reine Fakten wie Postleitzahlen, Gemeindenamen und Einwohnerzahlen sind für sich genommen nicht urheberrechtlich geschützt. Die Lizenz bezieht sich auf meine Aufbereitung und Zusammenstellung.
Alle Angaben ohne Gewähr. Verbindlich ist immer die jeweilige amtliche Originalquelle.
Fehler gefunden? Datensatz vermisst?
Das Repository ist öffentlich. Wenn Ihnen ein Fehler auffällt oder ein Datensatz fehlt, der hier gut hineinpassen würde, dann schreiben Sie mir. Ich pflege die Sammlung fortlaufend weiter.
Sie brauchen mehr als die Rohdaten?
Die CSV-Dateien sind der einfache Teil. Aufwendig wird es meist danach: Die Daten sollen regelmäßig aktualisiert in Ihre Datenbank fließen, mit Ihren eigenen Stammdaten abgeglichen werden, Dubletten sollen erkannt, Adressen normalisiert und Auswertungen automatisiert erstellt werden.
Genau das mache ich beruflich, seit über 20 Jahren: Datenintegration, Datenbankentwicklung und Automatisierung. Wenn Sie öffentliche Daten in Ihren Systemen nutzbar machen wollen und nicht wissen, wo Sie anfangen sollen, dann sprechen Sie mich an.