Skip to contents

What it covers

The Ballotpedia state elections scraper collects federal, state, and local candidate listings from Ballotpedia’s per-state election pages (e.g. https://ballotpedia.org/Maine_elections,_2024). Use office = "state_elections" to activate it.

Each page has three subsections — Federal Candidates, State Candidates, Local Candidates — which you can filter with the election_level argument.

Coverage: 2024 and 2025 page layouts are supported. Not all states have a Ballotpedia page for every year.

Vote counts require mode = "results", which follows each contest URL (one extra request per race). Use the default mode = "listings" for a fast candidate roster without vote data.


Arguments

Argument Default Description
office Must be "state_elections"
state required State name, title-case (e.g. "Maine", "Pennsylvania")
year NULL Single election year (e.g. 2024). Required for mode = "results".
election_level "all" Candidate tier to return — see below
mode "listings" What to return — see below
start_year 2024 Earliest year for multi-year listing scrape when year is NULL
end_year NULL Latest year (default: current calendar year)

The election_level parameter

Value Returns
"all" (default) All candidate tiers
"federal" U.S. House, U.S. Senate, Presidential Electors
"state" Governor, state legislature, attorney general, etc.
"local" Mayor, city council, county races, etc.

The mode parameter

Value Returns Speed
"listings" (default) One row per candidate from the state + year page; no vote counts Fast — 1 request
"results" All listing columns plus vote counts, percentages, and winner flags Slower — 1 extra request per unique contest

Examples

All candidates for a state — fast listing

maine_2024 <- scrape_elections(
  state  = "Maine",
  office = "state_elections",
  year   = 2024
)

maine_2024 %>%
  select(level, office, jurisdiction, district, candidate, party, status) %>%
  arrange(level, office)

Federal candidates only

scrape_elections(
  state          = "Pennsylvania",
  office         = "state_elections",
  year           = 2024,
  election_level = "federal"
) %>%
  select(office, jurisdiction, district, candidate, party, status)

Local candidates only

scrape_elections(
  state          = "Maine",
  office         = "state_elections",
  year           = 2024,
  election_level = "local"
) %>%
  select(jurisdiction, office, district, candidate, party, status) %>%
  arrange(jurisdiction, office)

Full results with vote counts

mode = "results" follows each contest link and returns votes and winner/incumbent flags:

maine_results <- scrape_elections(
  state  = "Maine",
  office = "state_elections",
  year   = 2024,
  mode   = "results"
)

# Winners only, sorted by vote share
maine_results %>%
  filter(is_winner) %>%
  arrange(desc(pct)) %>%
  select(level, office, jurisdiction, district, candidate, party, pct, votes)

Local results with vote counts

scrape_elections(
  state          = "Maine",
  office         = "state_elections",
  year           = 2024,
  election_level = "local",
  mode           = "results"
) %>%
  filter(is_winner) %>%
  select(jurisdiction, office, district, candidate, party, pct, votes) %>%
  arrange(jurisdiction, office)

State-level incumbents running for re-election

scrape_elections(
  state          = "Virginia",
  office         = "state_elections",
  year           = 2025,
  election_level = "state",
  mode           = "results"
) %>%
  filter(is_incumbent) %>%
  select(office, district, candidate, party, is_winner, pct, votes)

Multi-year listing (2024–2025)

Use start_year / end_year when year is omitted:

multi <- scrape_elections(
  state      = "Virginia",
  office     = "state_elections",
  start_year = 2024,
  end_year   = 2025
)

multi %>%
  group_by(year, level) %>%
  summarise(n_candidates = n(), .groups = "drop")

Columns returned

mode = "listings"

  • year, state, level (federal / state / local)
  • contest_name — raw office text as shown on Ballotpedia
  • contest_url — link to the individual election page
  • jurisdiction — parsed geographic area (e.g. "Maine", "Augusta")
  • office — parsed role (e.g. "U.S. Senate", "City Council")
  • district — parsed sub-race qualifier (e.g. "District 1", "At-large")
  • candidate, ballotpedia_url, party, status (e.g. "Won General", "Lost Primary")

mode = "results"

All listing columns plus:

  • election_type (General / Primary / Primary Runoff / General (RCV) / Other)
  • is_winner, is_incumbent
  • pct, votes

* Not all states have Ballotpedia state election pages for every year.