Data

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
Overview

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.

EndpointFormatContentParametersExample
/api/umfragenJSONOverview 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, CSVEverything 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/ergebnisseJSONAll official results since 2017 for the federal level, the states and the European election, newest first.none
/api/ergebnisse/{wahl}JSON, CSVAll results of one parliament since 2017, as JSON or CSV..csv at the end for the table
/api/verlauf/{wahl}JSONEvery single poll of recent years as a data point for trend charts.tage: period in days, 30 to 5000, default 730
/api/tickerJSONThe 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/amtsinhaberJSONMayors and district administrators of all municipalities and districts from Wikidata, keyed by municipality key (AGS) and district key.none
/api/personenJSONCompact 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/statusJSONData status of all sources: age of the dawum data, latest results per parliament, European polls, next elections, what runs automatically.none
/api/sucheJSONPlace search across municipalities, districts, constituencies and states, the ten best hits.q: search term (2+ characters)
/feed.xmlRSS 2.0The election ticker as an RSS feed, the 60 most recent items with permanent GUIDs.none
Fields

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

FieldMeaning
updatedtime of the last update at dawum
elections[].electionname of the election, e.g. Bundestagswahl
elections[].slugkey for the detail endpoints
elections[].as_ofdate of the average (most recent poll included)
elections[].polls_in_averagenumber of polls in the average
elections[].averageaverage per party in percent, keyed by party abbreviation
elections[].next_electiondate or expected period of the next election
elections[].page, json, csvaddresses of the page and the detail data
source, publishersource of the raw data with licence, publisher of the calculation

/api/umfragen/{wahl} JSON, CSV

FieldMeaning
as_of, next_election, methoddate of the average, next election, description of the method
averageaverage per party in percent
seatstotal, majority, method, threshold_percent and distribution (seats per party)
house_effectssince, institutes[] with polls and effects per party (percentage points), adjusted_average
last_electiondate, 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
probabilitiesruns, 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
citationready-made citation line with date, address and licence
CSV columnsinstitut; auftraggeber; veroeffentlicht; zeitraum_von; zeitraum_bis; befragte; methode; then one column per party. The first data row is the average.

/api/ergebnisse JSON

FieldMeaning
countnumber of elections
items[].parliament, election, dateslug, name and election day
items[].statusvorläufig (preliminary) or endgültig (final)
items[].resultsvote share per party in percent, keyed by dawum party ID
items[].othershare of other parties
items[].urlpage with the full result
partyIds, licensemapping of party IDs, licence of the raw data

/api/ergebnisse/{wahl} JSON, CSV

FieldMeaning
parliament, electionslug and name of the election
items[].date, status, results, other, urlas in /api/ergebnisse
CSV columnsdatum; status; partei_{id} per party; sonstige

/api/verlauf/{wahl} JSON

FieldMeaning
slug, tageelection and chosen period
points[].datepublication date of the poll
points[].instituteIddawum pollster ID
points[].valuespercent per party, keyed by dawum party ID

/api/ticker JSON

FieldMeaning
generated, countgeneration time and number of items
events[].id, date, kindkey, date, type (umfrage, ergebnis, kommunalwahl, europa, termin, personen)
events[].label, title, textcategory, headline, item text
events[].parties[]id, short and value of the parties mentioned, if any
events[].url, permalinktarget page and permanent address in the ticker
upcoming[]upcoming election dates in the same format

/api/amtsinhaber JSON

FieldMeaning
kreise{key}, gemeinden{ags}one object per area, keyed by the official area key
name, title, femalename, office title, gender
party, partyLabeldawum party ID (0 = independent, null = not stated) and party name from Wikidata
start, wikipedia, qidstart of term, Wikipedia article, Wikidata ID
sourcesource, licence and retrieval date

/api/personen JSON

FieldMeaning
total, offsettotal number of hits and start position
items[].s, nslug and name
items[].p, pidparty abbreviation and dawum party ID
items[].pl, parliamentparliament code and full name
items[].wkconstituency, if any
items[].tm = current mandate, k = candidacy
items[].img, urlphoto (if any) and profile page

/api/status JSON

FieldMeaning
generatedgeneration time
dawumsource (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

FieldMeaning
hits[].typeGemeinde, Kreis, Wahlkreis or Land
hits[].name, subname and addition (district, state or election)
hits[].hrefpath of the page

/feed.xml RSS 2.0

FieldMeaning
item.title, link, descriptioncategory and headline, target page, item text
item.guidpermanent address of the item in the ticker
item.category, pubDatecategory and date
Examples

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.

JavaScript (fetch)
// 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 coalition
Python (requests, pandas)
import 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="#")
R (jsonlite)
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")
curl
# 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.csv
Terms

Licence 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.

Operations

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.

Data status · /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.

Table as CSV

To download we need your e-mail address once. After that every table on the site downloads directly.