npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@maschinenlesbar.org/bundeswahlleiterin-cli

v0.0.3

Published

TypeScript API client and CLI for the Bundeswahlleiterin open data — German federal election (Bundestagswahl 2025) results, parties, constituencies and structural data

Readme

bundeswahlleiterin-cli

CI Release npm

Query the official German federal election results from your terminal. bundeswahl is a command-line tool over the Bundeswahlleiterin open data for the Bundestagswahl 2025: first- and second-vote results by Bund, Land and Wahlkreis, the parties, the 299 constituencies, and per-constituency structural data — as clean JSON you can pipe straight into jq.

  • The official result — the Amtliches Endergebnis (kerg2), one row per area × party × ballot, filterable by area, party and Erst-/Zweitstimme.
  • Reference data — parties, the 299 Wahlkreise (by Land), and Strukturdaten (demographics) per constituency.
  • Open data — Datenlizenz Deutschland – Namensnennung 2.0. No API key; free to reuse (incl. commercially) with attribution — see DATA_LICENSE.md.
  • Clean JSON output — pretty by default, --compact for scripting, -o <file> to write to disk; counts and percentages come back as numbers.

Want to use this as a TypeScript library, or curious how it parses the CSV files with zero dependencies? See DEVELOPING.md.

Install

npm i -g @maschinenlesbar.org/bundeswahlleiterin-cli

This installs the bundeswahl command. Requires Node.js 20+. No API key.

Check it works:

bundeswahl results --area-type Bund --vote 2 --group-type Partei | jq '.[] | {party: .gruppenname, pct: .prozent}'

Quickstart

# National second-vote (Zweitstimme) result for one party
bundeswahl results --area-type Bund --vote 2 --party SPD

# Who won the direct mandate (Erststimme) in Kiel, and by how much?
bundeswahl results --area Kiel --vote 1 --group-type Partei \
  | jq -r 'sort_by(-.anzahl)[] | "\(.gruppenname)\t\(.anzahl)\t\(.prozent)%"'

# The 299 constituencies in Bavaria
bundeswahl wahlkreise --land Bayern | jq -r '.[].name'

# Structural data for one Wahlkreis
bundeswahl structure --wahlkreis Kiel

Commands

| Command | What it shows | | --- | --- | | results | Bundestagswahl 2025 results — one row per area × party × ballot (--area-type, --area, --party, --vote, --group-type) | | parties | The parties / groups reference list | | wahlkreise | The 299 constituencies (--land <name\|abbr\|number>) | | structure | Structural data (Strukturdaten) per Wahlkreis (--wahlkreis <nr\|name>) |

New to terms like Wahlkreis, Erststimme/Zweitstimme, kerg2, Gebietsart or Gruppenart? The Glossary decodes every one.

results filters

| Option | Meaning | | --- | --- | | --area-type <level> | Bund | Land | Wahlkreis | | --area <nr-or-name> | an area by exact number (005, 09) or name substring (Kiel) | | --party <name> | a party/group by name substring (SPD, GRÜNE), case-insensitive | | --vote <1\|2> | 1/erst = Erststimme, 2/zweit = Zweitstimme | | --group-type <type> | a GruppenartPartei, System-Gruppe, Einzelbewerber/Wählergruppe |

Filters apply client-side (each command fetches the whole dataset), so they compose and an unmatched filter yields [].

Output & scripting

Every command prints JSON to stdout; diagnostics go to stderr, so piping into jq stays clean. Counts (anzahl) are integers and shares (prozent) are numbers; empty/placeholder cells are null.

# Second-vote national shares, sorted
bundeswahl results --area-type Bund --vote 2 --group-type Partei \
  | jq -r 'sort_by(-.prozent)[] | "\(.gruppenname)\t\(.prozent)%"'

# Turnout (Wahlbeteiligung) nationally
bundeswahl results --area-type Bund --group-type System-Gruppe \
  | jq -r '.[] | select(.gruppenname=="Wählende") | .prozent'

Use --compact for single-line JSON and -o <file> to write to a file — both are global options that work before or after the command.

Exit codes make the CLI easy to use in scripts:

| Code | Meaning | | --- | --- | | 0 | Success (also --help / --version) | | 2 | Bad usage / invalid argument (nothing was sent) | | 4 | Not found (404 — a data file moved) | | 6 | Network / transport failure (DNS, connection, timeout, size cap) | | 1 | Any other error — including a non-CSV response (an HTML page instead of the file) |

Troubleshooting

  • command not found: bundeswahl — the global npm bin directory isn't on your PATH. Run npm bin -g to find it and add it, or run via npx @maschinenlesbar.org/bundeswahlleiterin-cli ….
  • Exit 4 / "not found" — a data file moved. The Bundeswahlleiterin open-data URLs (some behind dam/jcr identifiers) are pinned in the client; if the section is reorganised, a path needs updating.
  • Exit 1 / "received an HTML page" — the request returned an HTML page instead of a CSV (a moved file, or a custom --base-url).
  • Empty [] — the filter matched nothing; broaden --area/--party, or check the value against parties / wahlkreise.

Global options

Given before or after the command, e.g. bundeswahl --compact results:

| Option | Description | | --- | --- | | -V, --version | Print the version number | | -h, --help | Show help for the program or a command | | --compact | Print JSON on a single line instead of pretty-printed | | -o, --output <file> | Write output to this file instead of stdout. Refuses to overwrite an existing file unless --force is given | | -f, --force | With --output, overwrite the target file if it already exists | | --base-url <url> | Data host base URL (default https://www.bundeswahlleiterin.de) | | --timeout <ms> | Per-request timeout (default 30000) | | --user-agent <ua> | User-Agent header value | | --max-retries <n> | Retries for transient 429/503 responses (0..10, default 2) | | --max-response-bytes <n> | Cap response body size in bytes (0 = unlimited; default 100 MiB) |

Learn more

  • SKILLS.md — Claude Code Agent Skills that drive this CLI.
  • Usage.md — full use-case-driven cookbook.
  • GLOSSARY.md — every domain term explained.
  • DEVELOPING.md — TypeScript library usage, the CSV parser, architecture, testing, CI.

Data license

This CLI is a client — it accesses data it does not own or redistribute. The upstream data is © the Bundeswahlleiterin and licensed separately from this tool's code. See DATA_LICENSE.md.

Bundeswahlleiterin — the open data is Datenlizenz Deutschland – Namensnennung 2.0: freely reusable, including commercially, with attribution. Cite "Quelle: Die Bundeswahlleiterin, Wiesbaden 2025".

License

Dual-licensed — use it under either:

  • AGPL-3.0-or-later (default, free). Note the AGPL's §13 network clause: if you run a modified version as a network service, you must offer that modified source to the service's users.
  • Commercial license (paid), for closed-source / proprietary or SaaS use without the AGPL's obligations.

See LICENSING.md for details, and CONTRIBUTING.md for the contribution policy (this project does not accept external code contributions). Commercial enquiries: [email protected].