Data
The full database underlying every figure on this site, in two formats. No signup, no rate limit, no abridged view.
Snapshot 19 May 2026 · 10 cycles · 31,888 races · 46,737 elected seats · 1,507 council×cycle pairs. Sources listed under Licensing & sources.
Parliamentary general-election downloads (CSV per year, separate schema) live at /parliament/data — not mixed into this list to keep council and parliamentary datasets clearly distinct.
Downloads
- results.sqlite — full database for all cycles (open in DBeaver, sqlite3, DuckDB CLI, Python, R, or any SQLite-compatible tool).
- cycles.csv — one row per election cycle
- councils.csv — one row per (year, council) pair
- races.csv — one row per ward race
- candidates.csv — one row per candidacy
Browse in your browser
Run SQL against the database without installing anything, via Datasette Lite (Simon Willison's Datasette compiled to WebAssembly). Once loaded, every query runs locally in your browser — nothing is sent to a server.
Open the database in Datasette Lite ↗
Opens in a new tab and downloads the SQLite file (~32 MB) on first load.
Schema
All tables are keyed by year as the leading column;
everything else joins on (year, council_slug) and (year, council_slug, ward_slug).
cycles
year | Election year (primary key) |
|---|---|
election_date | ISO date the polls were held |
council_count, race_count, seat_count | Volumetrics for the cycle |
below_quota_seat_count, below_quota_share | Seats whose marginal candidate share fell below the proportional quota |
councils
year, council_slug | Composite primary key |
|---|---|
council | Display name (Lower-tier authority) |
authority_type | UC / MD / LB / SD / etc. |
race_count | Ward races in this council in this cycle |
total_seats, below_quota_seats, below_quota_share | Per-(year, council) aggregates |
races
year, council_slug, ward_slug | Composite primary key |
|---|---|
ec_code | Electoral Commission ward code where the source provides one (null for 2023) |
ward_name, council | Display labels |
seats | Seats contested in this ward |
electorate, ballots, invalid_votes | Source figures (some null in earlier years) |
valid_ballots | Sum of candidate votes — the LEH "Valid vote turnout (HoC method)" denominator |
winning_pct | Marginal-elected-candidate share of valid ballots |
quota | Proportional quota: 1.0 / (seats + 1) |
under_par | winning_pct − quota — signed gap (negative = below quota, positive = above). Field name kept for schema compatibility; the convention is signed-gap. |
is_below_quota | 1 when winning_pct < quota |
candidates
year, council_slug, ward_slug | Joins races |
|---|---|
candidate_name, party | Public election record (party normalised to canonical full name) |
votes | Votes cast for this candidate |
elected | 1 if elected — recomputed as top-N-by-votes (see methodology) |
elected_source | The LEH source Elected flag, before our correction; differs on a small number of candidacies where the workbook is internally inconsistent |
rank | 1 = highest-vote candidate in the ward |
Licensing & sources
Election results — published by the House of Commons Library under the Open Parliament Licence; ingested from the annual Local Election Handbook for each cycle.
Council composition snapshots — per-council per-party seat counts by year, sourced from opencouncildata under CC BY-SA 4.0 (attribution: opencouncildata.co.uk). Used for the truth-set running composition on each council page and for the council-control flip definition.
Our derived columns (winning_pct, quota, under_par, the below_quota_* aggregates,
and the council-flip computation) are released under CC BY-SA 4.0.
Attribution: "electionresults.uk".