Scraping election data with DownBallotR
Source:vignettes/articles/scraping-data.Rmd
scraping-data.RmdPrerequisites
Before scraping data you need a working Python environment. If you have not done so yet, follow the steps in the Python setup vignette:
# One-time setup (downloads ~100-200 MB the first time)
downballot_install_python()At the start of each R session:
The single entry point: scrape_elections()
All data retrieval flows through one function:
scrape_elections(state, ...)The scraper is selected automatically based on
state — you never need to specify a backend by name:
| Priority | Condition | Scraper used |
|---|---|---|
| 1 |
state is North Carolina |
North Carolina State Board of Elections scraper (2000–present) |
| 2 |
state is Connecticut |
Connecticut CTEMS scraper (2016–present) |
| 3 |
state is Georgia |
Georgia Secretary of State scraper (2000–present) |
| 4 |
state is Utah |
Utah election results scraper (2023–present) |
| 5 |
state is Indiana |
Indiana voters portal scraper (2019–present) |
| 6 |
state is Louisiana |
Louisiana Secretary of State scraper (1982–present) |
| 7 | All other states | ElectionStats multi-state scraper |
Data availability
Use db_available_years() to check available year ranges
programmatically:
# All sources
db_available_years()
# Filter to one state
db_available_years(state = "Virginia")| Source | State | Start year | End year |
|---|---|---|---|
| ElectionStats | Vermont | 1789 | 2024 |
| ElectionStats | Virginia | 1789 | 2025 |
| ElectionStats | Colorado | 1902 | 2024 |
| ElectionStats | Massachusetts | 1970 | 2026 |
| ElectionStats | New Hampshire | 1970 | 2024 |
| ElectionStats | Idaho | 1990 | 2024 |
| ElectionStats | New York | 1994 | 2024 |
| ElectionStats | New Mexico | 2000 | 2024 |
| ElectionStats | South Carolina | 2008 | 2025 |
| North Carolina State Board of Elections | North Carolina | 2000 | present |
| Connecticut CTEMS | Connecticut | 2016 | present |
| Georgia Secretary of State | Georgia | 2000 | present |
| Utah elections site | Utah | 2023 | present |
| Indiana voters portal | Indiana | 2019 | present |
| Louisiana Secretary of State | Louisiana | 1982 | present |
To see which states are supported by the ElectionStats scraper:
db_list_states("election_stats")
#> [1] "Colorado" "Idaho" "Massachusetts" "New Hampshire"
#> [5] "New Mexico" "New York" "South Carolina" "Vermont"
#> [9] "Virginia"Choosing the right scraper
Note on
level: Thelevelargument selects the constituency level of the returned results — i.e., the geographic unit at which votes are tabulated. For example,level = "state"returns state-level constituency (statewide) results,level = "county"returns county-level constituency results, andlevel = "precinct"returns precinct-level constituency results. This is not the same as office level (Federal / State / Local).
| Goal | Call |
|---|---|
| Candidate + vote totals for Colorado, Massachusetts, New Hampshire, Idaho, Vermont (classic) | scrape_elections(state = "virginia", ...) |
| Precinct-level results for Colorado, Massachusetts, Idaho (classic) | scrape_elections(state = "colorado", year_from = 2022, year_to = 2022, level = "precinct") |
| Candidate + vote totals for South Carolina, New Mexico, Virginia, New York (Playwright) | scrape_elections(state = "south_carolina", ...) |
| Precinct-level results for South Carolina, New Mexico, Virginia (v2 CSV API) | scrape_elections(state = "new_mexico", year_from = 2024, year_to = 2024, level = "precinct") |
| North Carolina precinct-level local results | scrape_elections(state = "north_carolina", year_from = 2025, year_to = 2025) |
| Connecticut statewide + town results | scrape_elections(state = "connecticut", year_from = 2024, year_to = 2024) |
| Connecticut statewide totals only (faster) | scrape_elections(state = "connecticut", year_from = 2024, year_to = 2024, level = "state") |
| Georgia statewide + county + precinct results | scrape_elections(state = "georgia", year_from = 2024, year_to = 2024) |
| Georgia statewide + county only (faster) | scrape_elections(state = "georgia", year_from = 2024, year_to = 2024, level = "county") |
| Georgia with vote-method breakdown | scrape_elections(state = "georgia", year_from = 2024, year_to = 2024, include_vote_methods = TRUE) |
| Georgia precinct-level only | scrape_elections(state = "georgia", year_from = 2024, year_to = 2024, level = "precinct") |
| Utah statewide + county + precinct results | scrape_elections(state = "utah", year_from = 2024, year_to = 2024) |
| Utah statewide + county only (faster) | scrape_elections(state = "utah", year_from = 2024, year_to = 2024, level = "county") |
| Utah statewide only (fastest) | scrape_elections(state = "utah", year_from = 2024, year_to = 2024, level = "state") |
| Utah precinct-level only | scrape_elections(state = "utah", year_from = 2024, year_to = 2024, level = "precinct") |
| Indiana statewide + county General Election results | scrape_elections(state = "indiana", year_from = 2024, year_to = 2024) |
| Indiana statewide only (faster) | scrape_elections(state = "indiana", year_from = 2022, year_to = 2022, level = "state") |
| Louisiana statewide + parish results | scrape_elections(state = "louisiana", year_from = 2024, year_to = 2024) |
| Louisiana statewide only (faster; skips parish scraping) | scrape_elections(state = "louisiana", year_from = 2023, year_to = 2023, level = "state") |
Next: analyzing the data
Once you have a scraped data frame, the Example analyses vignette walks through worked example questions — wins by party, closest races, down-ballot drop-off, county-level variation, and cross-state comparisons — with tidyverse code you can adapt to your own scrapes.
Detailed articles
Each scraper has its own article with full argument documentation, worked examples, and column descriptions (available on the package website):
- ElectionStats states — Virginia, Massachusetts, Colorado, New Hampshire, Idaho, Vermont (classic) + South Carolina, New Mexico, New York (Playwright); candidate + county + precinct results
- North Carolina — North Carolina State Board of Elections; precinct-level results
- Connecticut — Connecticut CTEMS; statewide + town results, 2016–present
- Georgia — Georgia Secretary of State; statewide + county + precinct results, 2000–present
- Utah — Utah elections site; statewide + county + precinct results, 2023–present
- Indiana — Indiana voters portal; statewide + county General Election results, 2019–present
- Louisiana — Louisiana Secretary of State; statewide + parish results, 1982–present
Performance tips
- Start small — test with a single year and state before requesting large date ranges.
- Playwright states are slower — South Carolina, New Mexico, and New York launch a headless browser for each scrape. Expect several seconds per year.
-
Parallel scraping is on by default for classic
(requests-based) ElectionStats states. Pass
parallel = FALSEto disable. - Be polite — built-in delays are intentional. Do not reduce or disable them; excessive requests may result in temporary IP blocks.