Skip to main content

elections

A unified Python interface to multiple election data sources from around the world.

Overview

The elections package provides easy access to various election data APIs through a consistent interface. Whether you need U.S. federal campaign finance data, international parliamentary statistics, or real-time election results, this package offers a simple way to access it all.

Installation

pip install elections

Note: Some data sources require additional dependencies (pandas, py2store) which will be installed automatically.

General Interface

The package provides a dictionary-like interface to access different data source modules:

from elections import ElectionsDataModules

# Access all data source modules
modules = ElectionsDataModules()

# List available sources
print(list(modules))
# ['nytimes', 'openfec', 'google_civic', 'democracy_works', 'ipu_parline']

Available Data Sources

  • nytimes: New York Times election results (2016, 2020, 2024) - No API key required
  • openfec: Federal Election Commission campaign finance data - Optional API key
  • google_civic: Google Civic Information API (polling, representatives, voter info) - API key required
  • democracy_works: Democracy Works election guidance (dates, deadlines, locations) - No API key required
  • ipu_parline: Inter-Parliamentary Union global parliamentary data - No API key required

Usage Examples

OpenFEC - Federal Campaign Finance

Access U.S. federal campaign finance data, including candidates, committees, and contributions:

from elections import ElectionsDataModules

modules = ElectionsDataModules()

# Get OpenFEC module
openfec = modules["openfec"]

# Get 2024 presidential candidates
candidates = openfec.get_candidates(year=2024, office="president")
print(f"Found {len(candidates['results'])} candidates")

# Search for specific candidate
results = openfec.search_candidates("Biden", year=2024)

# Get financial totals for a candidate
totals = openfec.get_candidate_totals("P80001571", year=2020)

API Key: Optional for higher rate limits. Get a free key at https://api.open.fec.gov/developers/

Google Civic Information

Get voter information, polling locations, and representatives:

from elections import ElectionsDataModules

modules = ElectionsDataModules()

# Get Google Civic module
civic = modules["google_civic"]

# Get voter information for an address
info = civic.get_voter_info(
    "1600 Pennsylvania Ave NW, Washington, DC", api_key="YOUR_KEY"
)

# Get representatives for an address
reps = civic.get_representatives("340 Main St, Venice, CA 90291", api_key="YOUR_KEY")

# Get list of available elections
elections = civic.get_elections(api_key="YOUR_KEY")

API Key: Required. Get a free key at https://console.developers.google.com/

IPU Parline - International Parliamentary Data

Access global parliamentary and election data for 190+ countries:

from elections import ElectionsDataModules

modules = ElectionsDataModules()

# Get IPU Parline module
ipu = modules["ipu_parline"]

# Get parliament information for France
france = ipu.get_parliament("FRA")

# Get election results for Germany
results = ipu.get_election_results("DEU")

# Get women in parliament statistics
stats = ipu.get_women_in_parliament("SWE")

# Get list of all countries
countries = ipu.get_country_list()

API Key: Not required

Democracy Works

Get U.S. election dates, deadlines, and voting locations:

from elections import ElectionsDataModules

modules = ElectionsDataModules()

# Get Democracy Works module
dw = modules["democracy_works"]

# Get upcoming elections
upcoming = dw.get_upcoming_elections(region="PA", days_ahead=60)

# Get elections for a specific state
state_elections = dw.get_state_elections("CA")

# Get all elections
elections = dw.get_elections()

API Key: Not required

New York Times Election Results

Access historical U.S. election results (2016, 2020, 2024):

from elections import ElectionsDataModules

modules = ElectionsDataModules()

# Get NYT module
nyt = modules["nytimes"]

# Get election data for a state
data = nyt.get_election_data("florida", year=2020)

# Get all races for a state
races = nyt.get_races("pennsylvania", year=2020)

# Get president race time series
timeseries = nyt.get_president_timeseries("georgia", year=2020)

API Key: Not required

Direct Module Import

You can also import data source modules directly:

# Import specific modules
from elections import openfec, google_civic, ipu_parline

# Use them directly
candidates = openfec.get_candidates(year=2024, office="president")
info = google_civic.get_voter_info("1600 Pennsylvania Ave", api_key="YOUR_KEY")
france = ipu_parline.get_parliament("FRA")

Consistent Parameter Names

Across all modules, we use consistent parameter names:

  • year: Election year (e.g., 2020, 2024)
  • region: Geographic region (state abbreviation like 'PA', or state name)
  • api_key: API authentication key (when required)
  • race_type: Type of race (e.g., 'president', 'senate', 'house')
  • office: Office being sought (used by some APIs)

API Keys Setup

Set API keys via environment variables for convenience:

export OPENFEC_API_KEY='your_openfec_key'
export GOOGLE_CIVIC_API_KEY='your_google_key'

Specific Example: 2020 US elections

Easy access to (US 2020) election statistics.

Yes, you can do it via our general interface, doing:

from elections import ElectionsDataModules

modules = ElectionsDataModules()

nyt = modules["nytimes"]
data = nyt.get_election_data("florida", year=2020)

But here's another convenient dict-like interface that was made based on it.

import pandas as pd
from elections import President2020TimeSeries, Races2020, Election2020RawJson

President's race stats

from elections import President2020TimeSeries

s = President2020TimeSeries()
len(s)
# Returns: 51

s is a dictionary-like interface to the presidential race. Its keys are the states:

print(*s)
# alabama alaska arizona arkansas california colorado connecticut delaware
# district-of-columbia florida georgia hawaii idaho illinois indiana iowa kansas
# kentucky louisiana maine maryland massachusetts michigan minnesota mississippi
# missouri montana nebraska nevada new-hampshire new-jersey new-mexico new-york
# north-carolina north-dakota ohio oklahoma oregon pennsylvania rhode-island
# south-carolina south-dakota tennessee texas utah vermont virginia washington
# west-virginia wisconsin wyoming

Its values are dataframes containing the stats:

state = "georgia"
df = s[state]
df
timestamp votes eevp eevp_source trumpd bidenj
2020-11-04T09:23:03Z 0 0 edison 0.000 0.000
2020-11-04T00:14:11Z 408 0 edison 0.674 0.326
2020-11-04T00:15:51Z 127106 2 edison 0.370 0.618
2020-11-04T00:19:55Z 173638 3 edison 0.431 0.557
... ... ... ... ... ...
2020-11-06T23:45:40Z 4970093 99 edison 0.493 0.494

456 rows × 5 columns

df["bidenj"].plot(figsize=(16, 6), grid=True, title=state)

Biden vote share over time in Georgia

Other races

But that's not the only race going on here.

from elections import Races2020

s = Races2020()
len(s)
# Returns: 51
data = s["new-york"]  # by the way, you can tab-complete this in a jupyter notebook
print(type(data))
# <class 'py2store.base.Store'>

print(f"{len(data)} items... Here are the first 5:")
list(data)[:5]
# ['president-general-2020-11-03',
#  'house-general-district-001-2020-11-03',
#  'house-general-district-002-2020-11-03',
#  'house-general-district-003-2020-11-03',
#  'house-general-district-004-2020-11-03']

So we see that now, instead of just getting the president's race, we get... 242 races (one of which is the president's race).

What you need to know is that President2020TimeSeries just gave you one of the many data fields available for the race (the 'timeseries' one), extracted and formatted for your convenience, since it's probably the main information you're here for.

But there are other associated (raw) data fields you may or may not be interested in. Here's what you got:

data[
    "president-general-2020-11-03"
].keys()  # you can tab complete here as well (you're welcome!)
# dict_keys(['race_id', 'race_slug', 'url', 'state_page_url', 'ap_polls_page',
#            'edison_exit_polls_page', 'race_type', 'election_type', 'election_date',
#            'runoff', 'race_name', 'office', 'officeid', 'race_rating', 'seat',
#            'seat_name', 'state_id', 'state_slug', 'state_name', 'state_nyt_abbrev',
#            'state_shape', 'party_id', 'uncontested', 'report', 'result',
#            'result_source', 'gain', 'lost_seat', 'votes', 'electoral_votes',
#            'absentee_votes', 'absentee_counties', 'absentee_count_progress',
#            'absentee_outstanding', 'absentee_max_ballots', 'provisional_outstanding',
#            'provisional_count_progress', 'poll_display', 'poll_countdown_display',
#            'poll_waiting_display', 'poll_time', 'poll_time_short', 'precincts_reporting',
#            'precincts_total', 'reporting_display', 'reporting_value', 'eevp',
#            'tot_exp_vote', 'eevp_source', 'eevp_value', 'eevp_display',
#            'county_data_source', 'incumbent_party', 'no_forecast', 'last_updated',
#            'candidates', 'has_incumbent', 'leader_margin_value', 'leader_margin_votes',
#            'leader_margin_display', 'leader_margin_name_display', 'leader_party_id',
#            'counties', 'votes2016', 'margin2016', 'clinton2016', 'trump2016',
#            'votes2012', 'margin2012', 'expectations_text', 'expectations_text_short',
#            'absentee_ballot_deadline', 'absentee_postmark_deadline', 'update_sentences',
#            'race_diff', 'winnerCalledTimestamp', 'timeseries'])
t = data["president-general-2020-11-03"]
print(t["trump2016"], t["clinton2016"])
# 2819534 4556124

Election2020RawJson

But if you want even more raw data than the above, we can give that to you.

With Election2020RawJson you get access to the original full JSON.

from elections import Election2020RawJson
import pandas as pd

raw_jsons = Election2020RawJson()
json_data = raw_jsons["california"]

print(json_data.keys())
# dict_keys(['data', 'meta'])

print(json_data["meta"])
# {'version': 10403,
#  'track': '2020-11-03',
#  'timestamp': '2020-11-06T23:52:57.623Z'}

print(json_data["data"].keys())
# dict_keys(['races', 'party_control', 'liveUpdates'])

Party Control

party_df = pd.DataFrame(json_data["data"]["party_control"]).set_index("race_type").T
race_type house president senate
needed_for_control 218 270 50
total 435 538 100
no_election {} {} {'democrat': 35, 'republican': 30, 'other': 0}

Live Updates

updates_df = pd.DataFrame(json_data["data"]["liveUpdates"])
print(f"Total live updates: {len(updates_df)}")
# Total live updates: 449

Example entries from the 449 live updates:

id author location text
333 Nate Cohn in New York New ballots from Clark County (that's Las Vegas)...
332 Nate Cohn in New York The latest Arizona ballot releases aren't looking...
331 Nick Corasaniti in Philadelphia There are still 102,000 mail ballots to be counted...
330 Dave Philipps in Las Vegas Biden nets 2,520 votes in the Las Vegas area...

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

elections-0.0.4.tar.gz (68.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

elections-0.0.4-py3-none-any.whl (22.1 kB view details)

Uploaded Python 3

File details

Details for the file elections-0.0.4.tar.gz.

File metadata

  • Download URL: elections-0.0.4.tar.gz
  • Upload date:
  • Size: 68.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for elections-0.0.4.tar.gz
Algorithm Hash digest
SHA256 b0fc57feda1882573b61d7c91e0d73ee996da5c48a46295eea6a45321e247e09
MD5 98bf0992cd36e338f322a3b191a25dc1
BLAKE2b-256 2d13b49df06ba5a4be1f88c71db88762877c0212d87e5ad9400a7fe8330b1844

See more details on using hashes here.

File details

Details for the file elections-0.0.4-py3-none-any.whl.

File metadata

  • Download URL: elections-0.0.4-py3-none-any.whl
  • Upload date:
  • Size: 22.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for elections-0.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 3eacbfc2f20746ca0004e98dea954d5dbad569f77e101e1b51a701b115c31368
MD5 252daabd27ef406c2194ee5f60efd2f4
BLAKE2b-256 01f412faa0e56729a6ed093ad08c9bbafc0bbb4baf165490f12210d0e79c491a

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.0.4 This release

2 files

0.0.3

2 files

0.0.2

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page