RealClearPolitics APIrealclearpolitics.com ↗
Retrieve all polls from RealClearPolling's Latest Polls page — race names, pollsters, dates, and candidate results — via a single API endpoint.
What is the RealClearPolitics API?
The RealClearPolitics API exposes one endpoint, list_latest_polls, that returns up to roughly 190 poll rows covering approximately the last five weeks of polling data from RealClearPolling's All Latest Polls page. Each row includes the race name, race identifier, pollster, listed date, and per-candidate results, making it straightforward to build polling trackers, aggregators, or political dashboards without manually scraping the source.
curl -X GET 'https://api.parse.bot/scraper/cdd7ab9b-cbfc-49be-b347-7c03ec089ddb/list_latest_polls?as_of=2026-09-09T17%3A30%3A00Z&hours=36' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace realclearpolitics-com-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Walkthrough: RealClearPolling SDK — browse latest polls, inspect snapshot metadata."""
from parse_apis.realclearpolitics_com_api import RealClearPolling, InputFormatInvalid
client = RealClearPolling()
# List the most recent polls (all on the page), capped at 10 items.
for poll in client.polls.list(limit=10):
leaders = ", ".join(f"{c.name}: {c.value}" for c in poll.candidates)
print(f"{poll.date} {poll.race} ({poll.pollster}) {poll.spread} [{leaders}]")
# Fetch the full snapshot to read page-level metadata alongside the polls.
snapshot = client.poll_snapshots.fetch()
print(f"\nas_of: {snapshot.as_of} total_on_page: {snapshot.total_on_page} count: {snapshot.count}")
# Narrow to the last 24 hours and drill into the first result.
recent = client.polls.list(hours=24, limit=1).first()
if recent is not None:
print(f"\nMost recent poll: {recent.race} by {recent.pollster}")
print(f" spread: {recent.spread} ({recent.spread_party})")
print(f" race_url: {recent.race_url}")
# Demonstrate typed error handling for invalid input.
try:
client.poll_snapshots.fetch(hours=-1) # invalid window
except InputFormatInvalid as e:
print(f"\nCaught expected error: {e.message}")
print("\nexercised: polls.list / poll_snapshots.fetch / InputFormatInvalid")
Returns every poll listed on the RealClearPolling 'All Latest Polls' page in one request (one row per poll; the page currently carries roughly the last five weeks of polls, about 190 rows, and has no further pagination). Each row carries the race name, the race identifier, the pollster and its source link, the spread, and all candidate/option results as numbers. The page exposes only a calendar date per poll (midnight US Central), not a time of day of posting; this is stated explicitly in the response via posting_time_exposed=false and posting_time_note, and every row carries date_precision='day'. When hours is supplied, only polls whose listed calendar day overlaps the window (as_of minus hours, as_of] are returned; as_of defaults to the current UTC time. Omitting hours returns the whole page. total_on_page is the number of rows on the page before filtering and count the number returned; count can be 0 when no poll falls in the window, which is a valid empty result.
| Param | Type | Description |
|---|---|---|
| as_of | string | ISO 8601 datetime the window ends at (e.g. 2026-09-09T17:30:00Z); naive values are treated as UTC. Omitted = current UTC time. Only meaningful together with hours. |
| hours | integer | Recency window in hours ending at as_of. Integer from 1 to 8760; omitted = no filtering. Because the page only exposes a calendar day per poll, a poll is kept when any part of its listed day falls inside the window. |
{
"type": "object",
"fields": {
"as_of": "UTC ISO datetime the window ended at (current time when as_of was omitted)",
"count": "number of poll rows returned",
"hours": "window length applied, or null when no filtering was requested",
"polls": "array of poll rows: race_id (site race identifier, string), race (full race name), date (YYYY-MM-DD listed date), date_raw (site's date string, midnight US Central), date_precision ('day'), pollster, pollster_url (source link or null), spread (e.g. 'El-Sayed +3'), spread_party (party of the leader or null for non-partisan measures), candidates (array of {name, value number}), race_url (RealClearPolling race page)",
"cutoff": "UTC ISO datetime of the window start, or null when no filtering was requested",
"total_on_page": "number of poll rows on the page before filtering",
"posting_time_note": "plain-language statement of the date granularity and how the window filter treats it",
"posting_time_exposed": "boolean, always false: the page shows a calendar date per poll but no posting time"
},
"sample": {
"data": {
"as_of": "2026-09-09T17:30:00Z",
"count": 13,
"hours": 36,
"polls": [
{
"date": "2026-09-09",
"race": "2026 Michigan Senate - Rogers vs. El-Sayed",
"spread": "El-Sayed +3",
"race_id": "8802",
"date_raw": "Wed, 09 Sep 2026 00:00:00 -0500",
"pollster": "CNN",
"race_url": "https://www.realclearpolling.com/polls/senate/general/2026/michigan/rogers-vs-el-sayed",
"candidates": [
{
"name": "El-Sayed",
"value": 47
},
{
"name": "Rogers",
"value": 44
}
],
"pollster_url": "https://s3.documentcloud.org/documents/28608784/cnn-poll-conducted-by-ssrs-michigan.pdf",
"spread_party": "Democrat",
"date_precision": "day"
},
{
"date": "2026-09-09",
"race": "President Trump Job Approval",
"spread": "Disapprove +15",
"race_id": "8656",
"date_raw": "Wed, 09 Sep 2026 00:00:00 -0500",
"pollster": "Rasmussen Reports",
"race_url": "https://www.realclearpolling.com/polls/approval/donald-trump/approval-rating-2nd-term",
"candidates": [
{
"name": "Approve",
"value": 42
},
{
"name": "Disapprove",
"value": 57
}
],
"pollster_url": "https://www.rasmussenreports.com/public_content/politics/trump_administration_second_term/trump_approval_index_history_second_term",
"spread_party": null,
"date_precision": "day"
}
],
"cutoff": "2026-09-08T05:30:00Z",
"total_on_page": 190,
"posting_time_note": "The page lists each poll under a calendar date only (midnight, US Central, UTC-5); no time of day of posting is exposed. When a time window is applied, a poll is included if any part of its listed calendar day falls inside the window.",
"posting_time_exposed": false
},
"status": "success"
}
}About the RealClearPolitics API
What the API Returns
The single list_latest_polls endpoint returns a flat array of poll rows, one per poll listed on RealClearPolling's All Latest Polls page. Each row in the polls array includes race_id (the site's own race identifier), race (the full race name), date (the listed date in YYYY-MM-DD format), date_raw (the date string exactly as it appears on the page), and per-candidate result fields. The response envelope also reports count (rows returned after filtering), total_on_page (rows before filtering), as_of, and cutoff.
Filtering by Recency
Two optional parameters let you narrow results to a recent window. hours accepts an integer from 1 to 8760 and defines how far back from as_of to include polls. as_of accepts an ISO 8601 datetime (naive values are treated as UTC); omitting it defaults to the current time. Because the page exposes only a calendar date per poll — no posting time — the posting_time_exposed field is always false, and posting_time_note describes in plain language how the window filter handles that ambiguity. When no filtering is requested, hours and cutoff are both returned as null.
Coverage and Pagination
The page carries no further pagination; one call returns the full contents — roughly the last five weeks of polls at any given moment. The total available at any request is reflected in total_on_page. There is no endpoint for historical polls older than what the page currently shows, and no endpoint for RealClearPolitics polling averages or individual race average pages.
The RealClearPolitics API is a managed, monitored endpoint for realclearpolitics.com — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when realclearpolitics.com changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official realclearpolitics.com API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Snapshot the current polling landscape across all tracked races in a single request using
list_latest_polls - Filter polls published in the last 24 or 48 hours via the
hoursparameter to build a daily polling digest - Track which pollsters (
raceand pollster fields) are most active in a given week - Feed candidate result fields into a chart to visualize head-to-head polling trends over the five-week window
- Monitor a specific race by filtering the returned
race_idvalues in your own application logic - Archive daily polling snapshots by calling the endpoint on a schedule and storing the
as_oftimestamped response
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 200 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
| Team | $300/mo | 20,000 | 300 req/min |
| Company | $1,000/mo | 100,000 | 500 req/min |
Each endpoint has a fixed posted price per successful call — most fall between 1 and 10 credits — shown on this API's page before you run it. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does RealClearPolitics have an official developer API?+
What does the `posting_time_note` field tell me, and why is `posting_time_exposed` always false?+
posting_time_exposed is always false to signal this. posting_time_note is a plain-language string explaining how the hours/as_of window filter treats polls when only a date is available — for example, whether a poll dated today is included or excluded at the boundary.How far back does the polling data go?+
Does the API return RealClearPolitics polling averages or race-level average pages?+
Can I filter results by a specific race or candidate?+
race_id and race fields you can use to filter client-side. You can fork this API on Parse and revise it to add server-side filtering by race identifier or candidate name.