Skip to contents

A single entry point that automatically routes to the appropriate scraper based on state. Use db_list_states("election_stats") to see states supported by the general-election scraper.

Usage

scrape_elections(
  state = NULL,
  year_from = NULL,
  year_to = NULL,
  level = c("all", "state", "county", "precinct", "town", "parish"),
  parallel = TRUE,
  max_workers = 4L,
  include_vote_methods = FALSE
)

Arguments

state

State name or 2-letter abbreviation, accepted in any case or spacing style (e.g. "VA", "virginia", "Virginia", "south_carolina", "SC"). The value is normalised automatically before being passed to the underlying scraper, so callers do not need to worry about the exact format.

year_from

Start year, inclusive (default NULL). When NULL, ElectionStats starts at 1789; all state-portal scrapers apply no lower bound (data is clamped to each scraper's earliest confirmed year).

year_to

End year, inclusive (default NULL). When NULL, the current calendar year is used as the upper bound.

level

What to return. "all" (default) returns a named list with $state, $county, and (when available) $precinct data frames (ElectionStats); $state and $county data frames (Georgia / Utah / Indiana); $state and $town data frames (Connecticut); $state and $parish data frames (Louisiana); or $precinct, $county, and $state data frames (NC). "state" returns statewide candidate-level results only; "county" returns county vote breakdowns (ElectionStats / Georgia / Utah / Indiana); "precinct" returns precinct-level vote breakdowns — columns: state, election_id, candidate_id, county, precinct, candidate, votes (ElectionStats classic states: CO, MA, ID; v2 states: SC, NM, VA; NC via state="NC"; Georgia and Utah — navigates county pages to find and scrape each precinct, columns: state, election_name, election_type, election_year, election_date, office_level, office, district, county, precinct, candidate, party, votes, vote_pct (write-ins are excluded, so column may not sum to 100\ precinct_winner, url); "town" returns town-level results only (Connecticut); "parish" returns parish-level results only (Louisiana).

parallel

(ElectionStats) Use parallel county scraping for classic (requests-based) states (default TRUE). Ignored automatically for Playwright-based states (SC, NM, NY, VA).

max_workers

(Georgia / Utah / Connecticut / Louisiana) Maximum number of parallel Chromium browsers (default 4L). For Georgia and Utah, controls county-level parallelism; for Connecticut, controls town-level parallelism; for Louisiana, controls parish-level parallelism (default is capped at 2 for LA). Ignored for all other states.

include_vote_methods

(Georgia only) If TRUE, also return a vote-method breakdown table (Advance in Person, Election Day, Absentee by Mail, Provisional) for Georgia results (default FALSE). Ignored for all other states.

Value

A data.frame, or a named list when level = "all": $state + $county (+ $precinct when available) for ElectionStats; $state + $county + $precinct for Georgia / Utah (or just $state / $county / $precinct alone when the corresponding level is specified); $state + $county for Indiana; $state + $town for Connecticut; $state + $parish for Louisiana; $precinct + $county + $state for North Carolina. Each component is also assigned directly into the calling environment (e.g. ga_state, ga_county) when level = "all".

Details

Routing rules (applied in order):

  1. state matches North Carolina (e.g. "NC", "north_carolina") → NC State Board of Elections scraper (2000–present).

  2. state matches Connecticut (e.g. "CT", "connecticut") → Connecticut CTEMS scraper (2016–present).

  3. state matches Georgia (e.g. "GA", "georgia") → Georgia Secretary of State scraper (2000–present).

  4. state matches Utah (e.g. "UT", "utah") → Utah election results scraper (2023–present).

  5. state matches Indiana (e.g. "IN", "indiana") → Indiana General Election results scraper (2019–present).

  6. state matches Louisiana (e.g. "LA", "louisiana") → Louisiana Secretary of State scraper (1982–present).

  7. All other states → ElectionStats multi-state scraper.

Examples

# \donttest{
# General election results — Virginia
df <- scrape_elections(state = "virginia", year_from = 2023, year_to = 2023,
                       level = "state")
#> Error: Scraping failed for Virginia (ElectionStats).
#> 
#>   Error: Python environment 'downballotR' does not exist.
#> Run downballots_install_python() first.
#> 
#>   If this looks like a bug or the data source may have changed,
#>   please file a report (including the error above) at:
#>   https://github.com/gchickering21/DownBallotR/issues

# General election results — Virginia, both state and county levels
res <- scrape_elections(state = "virginia", year_from = 2023, year_to = 2023)
#> Error: Scraping failed for Virginia (ElectionStats).
#> 
#>   Error: Python environment 'downballotR' does not exist.
#> Run downballots_install_python() first.
#> 
#>   If this looks like a bug or the data source may have changed,
#>   please file a report (including the error above) at:
#>   https://github.com/gchickering21/DownBallotR/issues
res$state   # candidate-level data frame
#> Error: object 'res' not found
res$county  # county vote breakdown data frame
#> Error: object 'res' not found

# North Carolina — single year
df <- scrape_elections(state = "NC", year_from = 2024, year_to = 2024)
#> Error: Scraping failed for North Carolina (NC State Board of Elections).
#> 
#>   Error: Python environment 'downballotR' does not exist.
#> Run downballots_install_python() first.
#> 
#>   If this looks like a bug or the data source may have changed,
#>   please file a report (including the error above) at:
#>   https://github.com/gchickering21/DownBallotR/issues

# Connecticut — statewide + town results for 2024
res <- scrape_elections(state = "CT", year_from = 2024, year_to = 2024)
#> Error: Scraping failed for Connecticut (CTEMS).
#> 
#>   Error: Python environment 'downballotR' does not exist.
#> Run downballots_install_python() first.
#> 
#>   If this looks like a bug or the data source may have changed,
#>   please file a report (including the error above) at:
#>   https://github.com/gchickering21/DownBallotR/issues
res$state  # statewide totals
#> Error: object 'res' not found
res$town   # town-level results
#> Error: object 'res' not found

# Connecticut — statewide only (faster; no town scraping)
df <- scrape_elections(state = "CT", year_from = 2024, year_to = 2024,
                       level = "state")
#> Error: Scraping failed for Connecticut (CTEMS).
#> 
#>   Error: Python environment 'downballotR' does not exist.
#> Run downballots_install_python() first.
#> 
#>   If this looks like a bug or the data source may have changed,
#>   please file a report (including the error above) at:
#>   https://github.com/gchickering21/DownBallotR/issues

# Connecticut — with more parallel workers
res <- scrape_elections(state = "CT", year_from = 2022, year_to = 2022,
                        max_workers = 4L)
#> Error: Scraping failed for Connecticut (CTEMS).
#> 
#>   Error: Python environment 'downballotR' does not exist.
#> Run downballots_install_python() first.
#> 
#>   If this looks like a bug or the data source may have changed,
#>   please file a report (including the error above) at:
#>   https://github.com/gchickering21/DownBallotR/issues

# Georgia — statewide + county results
res <- scrape_elections(state = "GA", year_from = 2024, year_to = 2024)
#> Error: Scraping failed for Georgia (GA Secretary of State).
#> 
#>   Error: Python environment 'downballotR' does not exist.
#> Run downballots_install_python() first.
#> 
#>   If this looks like a bug or the data source may have changed,
#>   please file a report (including the error above) at:
#>   https://github.com/gchickering21/DownBallotR/issues

# Georgia — statewide only (faster)
df <- scrape_elections(state = "GA", year_from = 2024, year_to = 2024,
                       level = "state")
#> Error: Scraping failed for Georgia (GA Secretary of State).
#> 
#>   Error: Python environment 'downballotR' does not exist.
#> Run downballots_install_python() first.
#> 
#>   If this looks like a bug or the data source may have changed,
#>   please file a report (including the error above) at:
#>   https://github.com/gchickering21/DownBallotR/issues

# Georgia — with vote-method breakdown
res <- scrape_elections(state = "GA", year_from = 2024, year_to = 2024,
                        include_vote_methods = TRUE)
#> Error: Scraping failed for Georgia (GA Secretary of State).
#> 
#>   Error: Python environment 'downballotR' does not exist.
#> Run downballots_install_python() first.
#> 
#>   If this looks like a bug or the data source may have changed,
#>   please file a report (including the error above) at:
#>   https://github.com/gchickering21/DownBallotR/issues

# Utah — statewide + county results
res <- scrape_elections(state = "UT", year_from = 2024, year_to = 2024)
#> Error: Scraping failed for Utah (electionresults.utah.gov).
#> 
#>   Error: Python environment 'downballotR' does not exist.
#> Run downballots_install_python() first.
#> 
#>   If this looks like a bug or the data source may have changed,
#>   please file a report (including the error above) at:
#>   https://github.com/gchickering21/DownBallotR/issues

# Indiana — General Election results (statewide + county)
res <- scrape_elections(state = "IN", year_from = 2024, year_to = 2024)
#> Error: Scraping failed for Indiana (enr.indianavoters.in.gov).
#> 
#>   Error: Python environment 'downballotR' does not exist.
#> Run downballots_install_python() first.
#> 
#>   If this looks like a bug or the data source may have changed,
#>   please file a report (including the error above) at:
#>   https://github.com/gchickering21/DownBallotR/issues
res$state   # statewide candidate totals
#> Error: object 'res' not found
res$county  # county-level breakdown
#> Error: object 'res' not found

# Indiana — statewide only (faster)
df <- scrape_elections(state = "IN", year_from = 2022, year_to = 2022,
                       level = "state")
#> Error: Scraping failed for Indiana (enr.indianavoters.in.gov).
#> 
#>   Error: Python environment 'downballotR' does not exist.
#> Run downballots_install_python() first.
#> 
#>   If this looks like a bug or the data source may have changed,
#>   please file a report (including the error above) at:
#>   https://github.com/gchickering21/DownBallotR/issues

# Louisiana — statewide + parish results
res <- scrape_elections(state = "LA", year_from = 2024, year_to = 2024)
#> Error: Scraping failed for Louisiana (voterportal.sos.la.gov).
#> 
#>   Error: Python environment 'downballotR' does not exist.
#> Run downballots_install_python() first.
#> 
#>   If this looks like a bug or the data source may have changed,
#>   please file a report (including the error above) at:
#>   https://github.com/gchickering21/DownBallotR/issues
res$state   # statewide candidate totals
#> Error: object 'res' not found
res$parish  # parish-level breakdown
#> Error: object 'res' not found

# Louisiana — statewide only (faster; skips parish scraping)
df <- scrape_elections(state = "LA", year_from = 2023, year_to = 2023,
                       level = "state")
#> Error: Scraping failed for Louisiana (voterportal.sos.la.gov).
#> 
#>   Error: Python environment 'downballotR' does not exist.
#> Run downballots_install_python() first.
#> 
#>   If this looks like a bug or the data source may have changed,
#>   please file a report (including the error above) at:
#>   https://github.com/gchickering21/DownBallotR/issues
# }