"Namentliche Abstimmungen" in the Bundestag
How do individual members of the federal German parliament (Bundestag) vote in "Namentliche Abstimmungen" (roll call votes)? How does the individual align with the different political parties? And how may the members vote on upcoming bills? The
bundestagcli provides tools to assist to answer those questions by providing tools download and transform the required data.
Data sources
The German parliament makes roll call votes available as XLSX / XLS files (and PDFs ¯\_(ツ)_/¯ ) here: https://www.bundestag.de/parlament/plenum/abstimmung/liste.
The NGO abgeordnetenwatch provides an open API for a variety of related data. They also provide a great way of inspecting the voting behavior of members of parliament and their (non-)responses to question asked by the public.
Insights from the collected data
"Fraktionszwang"
Do all the members of a party always follow the party line? Clearly not. But that "discipline" is similar across parties. The significant deviation are the factionless, as measured here using Shannon entropy. The curious mind could even estimate the energy it takes to enforce the disciplines.
Embedded members of parliament
As a side effect of trying to predict the vote of individual members of parliament, we can obtain embeddings for each member. Doing so for the 2017-2021 legislative period, we find that they cluster into governing coalition (CDU/CSU & SPD) and the opposition:
If you want to see more check out this site or this notebook.
How to install
pip install bundestag
or
uv install bundestag
to get access to the cli to download and transform bundestag roll call votes data from bundestag.de or abgeordnetenwatch.de.
By to keep things light the machine learning dependencies are made optional. If you want to get those and related functionality as well run
pip install bundestag[ml]
or
uv install bundestag[ml]
For development
git clone https://github.com/eschmidt42/bundestag
cd bundestag
make install-dev-env
How to use
The bundestag cli
A tool to assist with the data processing.
For an overview over commands run
bundestag --help
To get preprocessed data simply run
bundestag download huggingface
To download data from abgeordnetenwatch, for a specific legislature id
bundestag download abgeordnetenwatch 132
To transform the downloaded data run
bundestag transform abgeordnetenwatch 132
To find out the legislature id for the current Bundestag, visit abgeordnetenwatch.de and click on the "Open Data" button at the bottom of the page.
To download data from bundestag.de
bundestag download bundestag-sheets --do-create-xlsx-uris-json
Note that this is using selenium and is therefore starting a browser. Currently this is not using a headless browser so it is easy to see when the scraping should be broken.
To transform the downloaded data run
bundestag transform bundestag-sheet --sheet-source=json_file
Note: If you run the extraction for the legislature with id 132, i.e.
bundestag transform abgeordnetenwatch 132
the data is damaged for some reason. To fix it run
uv run python scripts/fix_empty_fraction.py
download commands will store artefacts in ./data/raw and transform commands will transform that data and store artefacts in ./data/preprocessed.
The get_xlsx_uris cli
Pre-processing cli for bundestag cli.
uv run get_xlsx_uris run --help
Module for collecting and storing XLSX URIs from Bundestag data sources. Also done with
bundestag download bundestag_sheet --do-create-xlsx-uris-json
Notebooks
Metadata
Release files for bundestag 0.1.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| bundestag-0.1.3.tar.gz | 10.6 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| bundestag-0.1.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 10.7 MB
Release files / bundestag-0.1.3.tar.gz
| Download URL | bundestag-0.1.3.tar.gz |
|---|---|
| Size | 10.6 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b3a3dde09e266fc4b58d191ef2e13e1bf68b1e8c90d2945d5fa1ad222506cc9f
|
|
BLAKE2b-256 checksum How to use checksums |
f536645f0325ba89fcc97a7f371b66583a7ab3f24f629a67d911aaa2c1896c4e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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 14, 2025.
Transparency logRelease files / bundestag-0.1.3-py3-none-any.whl
| Download URL | bundestag-0.1.3-py3-none-any.whl |
|---|---|
| Size | 62.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9586b3bde0abec7bae99f6a1a483ff53ad66cbd7af4f4cde56b66ea46566f6f3
|
|
BLAKE2b-256 checksum How to use checksums |
4cd40a222b6cc6519492e4c112c7ef6e267f28cf8e7fb28880ca5aff79f373b0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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 14, 2025.
Transparency log