Database and API
Everything on these pages is also machine-readable: polls and averages, seat distributions, coalitions and probabilities, official results since 2017, MPs, mayors and district administrators, the election ticker. No registration, no key, no limit in normal use. The only condition is attribution.
- Endpoints
- 11
- Licence
- ODbL, dl-de/by-2-0, CC0
- Updated
- daily, polls hourly
- Format
- JSON, CSV, RSS
All endpoints
All addresses are relative to https://wahlergebnisse.io. {wahl} stands for bundestagswahl, europawahl or the slug of a state such as bayern, nordrhein-westfalen or sachsen-anhalt. Percentages are numbers with one decimal, dates are ISO 8601, CSV uses semicolons and UTF-8.
| Endpoint | Format | Content | Parameters | Example |
|---|---|---|---|---|
/api/umfragen | JSON | Overview of all 18 parliaments with the current polling average, the number of polls included and links to the detail endpoints. | none | |
/api/umfragen/{wahl} | JSON, CSV | Everything about one election: average, seat distribution, house effects, last result with pollster accuracy, majority coalitions, majority probabilities and every poll included. | .csv at the end or ?format=csv for the table of polls | |
/api/ergebnisse | JSON | All official results since 2017 for the federal level, the states and the European election, newest first. | none | |
/api/ergebnisse/{wahl} | JSON, CSV | All results of one parliament since 2017, as JSON or CSV. | .csv at the end for the table | |
/api/verlauf/{wahl} | JSON | Every single poll of recent years as a data point for trend charts. | tage: period in days, 30 to 5000, default 730 | |
/api/ticker | JSON | The election ticker: every new poll, every official result, local election counts, changes of mandate and upcoming dates of the last 45 days, each item with a permanent address. | none | |
/api/amtsinhaber | JSON | Mayors and district administrators of all municipalities and districts from Wikidata, keyed by municipality key (AGS) and district key. | none | |
/api/personen | JSON | Compact list of all members of the Bundestag, the state parliaments and the European Parliament plus candidates of the last six months, filterable. | q: name search (2+ characters); parlament: code such as BT, EU, BY, NW; partei: dawum party ID; typ: m (mandate) or k (candidacy); limit: up to 300, default 100; offset | |
/api/status | JSON | Data status of all sources: age of the dawum data, latest results per parliament, European polls, next elections, what runs automatically. | none | |
/api/suche | JSON | Place search across municipalities, districts, constituencies and states, the ten best hits. | q: search term (2+ characters) | |
/feed.xml | RSS 2.0 | The election ticker as an RSS feed, the 60 most recent items with permanent GUIDs. | none |
What the responses contain
The most important fields per endpoint. Parties appear in the poll endpoints by their abbreviation (CDU/CSU, SPD, AfD …), in the results endpoints by the dawum party ID explained in the partyIds field.
/api/umfragen JSON
| Field | Meaning |
|---|---|
| updated | time of the last update at dawum |
| elections[].election | name of the election, e.g. Bundestagswahl |
| elections[].slug | key for the detail endpoints |
| elections[].as_of | date of the average (most recent poll included) |
| elections[].polls_in_average | number of polls in the average |
| elections[].average | average per party in percent, keyed by party abbreviation |
| elections[].next_election | date or expected period of the next election |
| elections[].page, json, csv | addresses of the page and the detail data |
| source, publisher | source of the raw data with licence, publisher of the calculation |
/api/umfragen/{wahl} JSON, CSV
| Field | Meaning |
|---|---|
| as_of, next_election, method | date of the average, next election, description of the method |
| average | average per party in percent |
| seats | total, majority, method, threshold_percent and distribution (seats per party) |
| house_effects | since, institutes[] with polls and effects per party (percentage points), adjusted_average |
| last_election | date, status, results per party, accuracy_of_final_polls[] with institute, poll_date, mean_abs_deviation, deviations |
| majority_coalitions[] | parties and seats of every combination above the majority |
| probabilities | runs, majority[] with parties and probability_percent, above_threshold and strongest per party |
| polls[] | institute, commissioned_by, published, fieldwork.start/end, respondents, method, results per party |
| citation | ready-made citation line with date, address and licence |
| CSV columns | institut; auftraggeber; veroeffentlicht; zeitraum_von; zeitraum_bis; befragte; methode; then one column per party. The first data row is the average. |
/api/ergebnisse JSON
| Field | Meaning |
|---|---|
| count | number of elections |
| items[].parliament, election, date | slug, name and election day |
| items[].status | vorläufig (preliminary) or endgültig (final) |
| items[].results | vote share per party in percent, keyed by dawum party ID |
| items[].other | share of other parties |
| items[].url | page with the full result |
| partyIds, license | mapping of party IDs, licence of the raw data |
/api/ergebnisse/{wahl} JSON, CSV
| Field | Meaning |
|---|---|
| parliament, election | slug and name of the election |
| items[].date, status, results, other, url | as in /api/ergebnisse |
| CSV columns | datum; status; partei_{id} per party; sonstige |
/api/verlauf/{wahl} JSON
| Field | Meaning |
|---|---|
| slug, tage | election and chosen period |
| points[].date | publication date of the poll |
| points[].instituteId | dawum pollster ID |
| points[].values | percent per party, keyed by dawum party ID |
/api/ticker JSON
| Field | Meaning |
|---|---|
| generated, count | generation time and number of items |
| events[].id, date, kind | key, date, type (umfrage, ergebnis, kommunalwahl, europa, termin, personen) |
| events[].label, title, text | category, headline, item text |
| events[].parties[] | id, short and value of the parties mentioned, if any |
| events[].url, permalink | target page and permanent address in the ticker |
| upcoming[] | upcoming election dates in the same format |
/api/amtsinhaber JSON
| Field | Meaning |
|---|---|
| kreise{key}, gemeinden{ags} | one object per area, keyed by the official area key |
| name, title, female | name, office title, gender |
| party, partyLabel | dawum party ID (0 = independent, null = not stated) and party name from Wikidata |
| start, wikipedia, qid | start of term, Wikipedia article, Wikidata ID |
| source | source, licence and retrieval date |
/api/personen JSON
| Field | Meaning |
|---|---|
| total, offset | total number of hits and start position |
| items[].s, n | slug and name |
| items[].p, pid | party abbreviation and dawum party ID |
| items[].pl, parliament | parliament code and full name |
| items[].wk | constituency, if any |
| items[].t | m = current mandate, k = candidacy |
| items[].img, url | photo (if any) and profile page |
/api/status JSON
| Field | Meaning |
|---|---|
| generated | generation time |
| dawum | source (api or snapshot), lastUpdate, ageHours, polls, latestPoll |
| results[] | per parliament lastElection, resultDate, status, missing, government, nextElection |
| europa[] | per country polls, latestPoll, retrieved, ageDays |
| upcoming[], automation[] | next elections and list of automated processes |
/api/suche JSON
| Field | Meaning |
|---|---|
| hits[].type | Gemeinde, Kreis, Wahlkreis or Land |
| hits[].name, sub | name and addition (district, state or election) |
| hits[].href | path of the page |
/feed.xml RSS 2.0
| Field | Meaning |
|---|---|
| item.title, link, description | category and headline, target page, item text |
| item.guid | permanent address of the item in the ticker |
| item.category, pubDate | category and date |
How to read the data
Four lines are enough. All endpoints except the place search send Access-Control-Allow-Origin: *, so calls from the browser work without a proxy.
// Federal polling average, seats and coalitions
const r = await fetch("https://wahlergebnisse.io/api/umfragen/bundestagswahl");
const d = await r.json();
console.log(d.as_of, d.average); // { "CDU/CSU": 27.5, "AfD": 24.0, ... }
console.log(d.seats.distribution); // seats per party
console.log(d.majority_coalitions[0].parties); // first majority coalitionimport requests, pandas as pd
d = requests.get("https://wahlergebnisse.io/api/umfragen/bayern").json()
polls = pd.DataFrame(d["polls"]) # one row per poll
print(d["as_of"], d["average"])
# or straight into a table
csv = pd.read_csv("https://wahlergebnisse.io/api/umfragen/bayern.csv", sep=";", comment="#")library(jsonlite)
d <- fromJSON("https://wahlergebnisse.io/api/umfragen/nordrhein-westfalen")
d$as_of
d$average # named list, percent per party
polls <- d$polls # data.frame, one row per poll
# official results since 2017 as CSV
e <- read.csv2("https://wahlergebnisse.io/api/ergebnisse/nordrhein-westfalen.csv")# overview of all parliaments
curl -s https://wahlergebnisse.io/api/umfragen | jq '.elections[] | {election, as_of}'
# election ticker of the last 45 days
curl -s https://wahlergebnisse.io/api/ticker | jq '.events[0]'
# save polls as CSV
curl -s -o polls-federal.csv https://wahlergebnisse.io/api/umfragen/bundestagswahl.csvLicence and attribution
Polls: the raw data comes from the dawum.de database and is licensed under the Open Database License (ODbL). The database provided here is a derivative database in the sense of the ODbL and is also licensed under ODbL: you may copy, modify and redistribute it, must credit dawum.de and wahlergebnisse.io, and must share derivative databases under the same licence. dawum.de, ODbL 1.0.
Official results: Federal Returning Officer and state returning officers, Data licence Germany, attribution 2.0 (dl-de/by-2-0). Local election results come from the official result displays of the election authorities. dl-de/by-2-0.
People: abgeordnetenwatch.de and Wikidata, both CC0. Photos only with the author and licence stated on the profile page.
Geodata: © GeoBasis-DE / BKG 2025 (administrative areas VG250), dl-de/by-2-0.
Averages, seat distributions, coalitions, probabilities, house effects and accuracy are wahlergebnisse.io's own calculations, described under Method. They may be used freely, including commercially, with attribution. Method.
Recommended citation
wahlergebnisse.io, Bundestagswahl: polling average as of 24 Sep 2026, https://wahlergebnisse.io/bundestagswahl (data: dawum.de, ODbL)The citation field in /api/umfragen/{wahl} contains this line ready-made with the current date. For official results please credit the returning officer, for people abgeordnetenwatch.de and Wikidata.
Updates
- Polls are reloaded from dawum.de on request after at most one hour; the JSON responses are cached for up to one hour (Cache-Control header).
- Official results, people, office holders, the election calendar and European polls flow into the repository daily via GitHub Actions and from there onto the site.
- On election night a dedicated job reads the returning officers' result displays every 15 minutes until the preliminary result is in.
- What was last updated and when is shown under /status and machine-readable under /api/status.
Charts instead of data?
If you need the finished charts, the embed page offers widgets and images with a source link for every election, municipality and constituency. Newsrooms have their own overview. Embed · For newsrooms.
Missing a field or a format? Write to info@bernard.digital.