The Australian Electoral Commission publishes detailed results for every federal election on their tally room at results.aec.gov.au. For elections from 2007 onwards, this includes first preference votes, two-party preferred, two-candidate preferred, booth-level results, polling place coordinates, Senate counts, enrolment, and turnout - all available as CSV downloads updated live on election night.
The catch is that each election has its own URL structure built around an internal event ID, column names shift between years without warning, and there is no API. Getting data out requires knowing the right URL pattern, handling inconsistencies across elections, and writing fresh code every time.
readaec wraps the AEC's CSV downloads in a consistent, tidy interface. One function call returns a clean data frame. Results are cached locally so you're not hitting the AEC's servers on every call. It covers all federal elections from 2007 to 2025 (including the Senate), House by-elections from 2008 to the 2026 Farrer by-election, and the 2023 referendum.
readaec covers federal elections from 2007 onwards. For everything outside that scope, here's where to look.
Federal elections, 2001–2022: eechidna bundles House of Representatives results from 2001 to 2022 as ready-to-use R data frames. Its standout feature is the census join - ABS demographic variables apportioned to electoral boundaries - making it the best option for socio-economic analysis of the Howard-to-Morrison era. It doesn't cover the Senate and stops at 2022. readaec and eechidna are complementary rather than competing.
Federal elections, pre-2001: The AEC provides ZIP archives for the 1993, 1996, and 1998 elections via their statistics download page, packaged as legacy fixed-width files - usable but not pleasant. For anything earlier, Adam Carr's Psephos archive is the canonical source, covering federal results back to 1901 in plain-text format. David Barry has done the hard work of combining Psephos with AEC digital records into a cleaner, more analysis-friendly series from 1901 to the present.
Federal and state elections: The Tally Room - run by psephologist Ben Raue - covers both federal and state elections across all Australian jurisdictions, plus New Zealand. Ben publishes clean booth-level CSVs with lat/lon coordinates in a consistent format, going back to roughly 2001. Recent elections are free; the historical back-catalogue is available via Patreon. The key difference from readaec is that Ben's federal data is manually curated and published as static files, whereas readaec pulls live from the AEC - making readaec better suited for programmatic access and the most current results. For state and territory elections, Ben's data is essentially the only structured source that exists.
install.packages("readaec")
# Or install the development version from GitHub
# install.packages("devtools")
devtools::install_github("charlescoverdale/readaec")library(readaec)
list_elections()
#> year event_id date type has_downloads
#> 1 2007 13745 2007-11-24 general TRUE
#> 2 2010 15508 2010-08-21 general TRUE
#> ...
#> 7 2025 31496 2025-05-03 general TRUE# Two-party preferred by division
get_tpp(2025)
# First preferences by candidate
get_fp(2025)
# Two-candidate preferred (who actually won each seat)
get_tcp(2025)
# Members elected
get_members_elected(2025)
# Turnout by division
get_turnout(2025)# All polling places nationally (with lat/lon coordinates)
get_polling_places(2025)
# Filter to a single division
get_polling_places(2025, division = "Kooyong")
# First preference votes at booth level
get_fp_by_booth(2025, state = "VIC")
# TPP at booth level
get_tpp_by_booth(2025)
# TCP at booth level
get_tcp_by_booth(2025)The full count-by-count preference distribution for every seat: each exclusion round and where the preferences flowed. This is the dataset for analysing seats won from second or third place, which TPP and TCP figures cannot show.
get_dop(2025)# First preferences by state
get_senate(2025)
# Senators elected, in order of election
get_senators_elected(2025)By-election results are published at polling place level. All 24 House by-elections with AEC CSV downloads are covered, from Gippsland 2008 to Farrer 2026.
list_by_elections()
# First preferences by booth
get_by_election_fp("Farrer")
# Two-candidate preferred by booth (the count that decided Farrer in 2026)
get_by_election_tcp("Farrer")
# Divisions with two by-elections need a year
get_by_election_tcp("Mayo", year = 2018)
# Candidates
get_by_election_candidates("Aston")Booth-level Yes/No results and turnout for the 2023 referendum on the Aboriginal and Torres Strait Islander Voice.
list_referendums()
# Yes/No votes at every polling place
get_referendum_by_booth(2023)
get_referendum_by_booth(2023, state = "TAS")
# Enrolment and turnout
get_referendum_turnout(2023)
get_referendum_turnout(2023, by = "state")# Full candidate list
get_candidates(2025)
get_candidates(2025, chamber = "senate")
# Enrolment by division
get_enrolment(2025)Because every function returns a consistent tidy data frame, combining elections is straightforward:
library(dplyr)
# How did Kooyong swing between 2019 and 2025?
bind_rows(
get_tpp(2019),
get_tpp(2022),
get_tpp(2025)
) |>
filter(division == "Kooyong") |>
select(year, alp_pct, lnp_pct, swing)Or use get_swing() for a direct comparison:
# National swing 2022 to 2025
get_swing(2022, 2025)
# Single seat
get_swing(2019, 2025, division = "Richmond")
# All Victorian seats
get_swing(2019, 2022, state = "VIC")Downloaded files are cached locally so repeated calls are instant. To clear the cache:
clear_cache()Every data function also takes refresh = TRUE to force a re-download, which matters on election night when cached counts go stale:
get_tpp(2025, refresh = TRUE)All data comes directly from the Australian Electoral Commission. Please respect their terms of use.
Please report bugs or requests at https://github.com/charlescoverdale/readaec/issues.