How-to
How to run Kalshi & Polymarket Election Odds History Scraper
Step-by-step: the exact input, what each field does, and the rows that come back from Kalshi + Polymarket.
You want the odds of an election market over its whole life, after it settled: the Arizona Senate race, every 2026 governor race, or the 2028 races that are trading now. Kalshi shows one chart per market on its site, and its public API answers one candlestick request per candidate. Oregon’s 2026 governor market alone ran from 2025-01-26 to 2026-11-04, so doing a cycle by hand means hundreds of requests, plus the 2024 races, which have moved to a separate archive path.
What you’ll need
Nothing but an Apify account. The actor talks to Kalshi + Polymarket directly.
Both venues publish keyless public APIs, so there is no API key to sign up for and no proxy to pay for. The proxy input is off by default, and the first run from Apify’s own servers on 2026-11-06 answered in 10 seconds without one.
Step 1 — Open the actor
Open Kalshi & Polymarket Election Odds History Scraper on the Apify Store and press Try for free. The actor’s own page on this site lists its live health and pricing.
Step 2 — Fill in the input
| Field | Type | Required | What it does |
|---|---|---|---|
queries | array | no | Races to pull, as words in the race’s title: ‘arizona senate’, ‘oregon governor’, ‘presidential election winner’. Every word must appear. Kalshi is matched on its election… (default []) |
query | string | no | One keyword. Kept alongside ‘Keywords’ for saved tasks and API callers. |
seriesTickers | array | no | Exact Kalshi series, e.g. SENATEAZ, GOVPARTYOR, HOUSEPA7, SENATENM. One series holds every cycle of that race (2024, 2026, 2028…). (default []) |
seriesTicker | string | no | One series ticker. Kept alongside ‘Kalshi series tickers’ for saved tasks and API callers. |
tags | array | no | Every Kalshi election series carrying any of these tags: Senate, House, Governor, Primaries, US Elections, Referendums, Local, 2028, International. Broad: combine with ‘Cycle’… (default []) |
venues | string | no | Kalshi, Polymarket or both. Both returns the same race from each venue as separate rows with a ‘venue’ field. (default both) |
cycle | string | no | Election year. Kalshi’s year comes from the race ticker (SENATEAZ-24), Polymarket’s from the market’s end date. (default any) |
status | string | no | Settled races (the default) carry the result and their whole history. Open races give the history so far. (default settled) |
granularity | string | no | One row per day or per hour of each candidate’s odds. Hourly is 24 times the rows (and the cost). (default daily) |
from | string | no | Only candles and trades from this date (YYYY-MM-DD). Empty = from the day the market opened. |
to | string | no | Only candles and trades up to this date (YYYY-MM-DD). Empty = until the market settled, or today if it is open. |
includeTrades | boolean | no | Every Kalshi trade: time, yes/no price, size and taker side. A busy race has tens of thousands; set dates or ‘Maximum rows’ to bound it. |
maxRaces | integer | no | Stop after this many races from each venue. (default 10) |
maxResults | integer | no | A cap on the whole RUN for candles plus trades: your spend control. Race and candidate rows are not counted. When it cuts the run short, a free ‘truncated’ row says so. (default 5000) |
Two fields decide what you get. The first is how you name the races: a keyword (“arizona senate”)
reaches both venues, a series ticker (SENATEAZ) reaches exactly one Kalshi race across every cycle,
and a tag (Senate) reaches every Kalshi series carrying it. Tags are wide. On 2026-11-06 the Senate
tag also held AP-call timing markets, governor-and-Senate combos and “How will Platner’s replacement
be chosen?”, so pair a tag with cycle and maxRaces. The second is from: left empty you get the
market’s whole life, which for Oregon’s governor market was 560 daily candles per candidate.
A working input:
{
"queries": [
"arizona senate"
],
"venues": "both",
"status": "settled",
"granularity": "daily"
}
Step 3 — Run it
Press Start. Rows are pushed to the dataset as they’re found, so the run log fills in as it works.
That input returned 5 races on 2026-11-06: Kalshi’s SENATEAZ-24 (won by Ruben Gallego) and 4
Polymarket events, including its margin-of-victory market and the 2022 Blake Masters nomination
question. Together they gave 14 candidate rows and 952 daily candles in about 16 seconds. An empty
run ends with one free no_match row naming the cycle and status it used; a wrong cycle filter is
the usual cause, since cycle: 2026 on SENATEAZ finds nothing (Arizona had no 2026 Senate race).
Step 4 — Read the output
Each run returns a labelled table, not raw JSON:
Every row looks like this — a real row from a real run:
{
"source_url": "https://api.elections.kalshi.com/trade-api/v2/historical/markets/SENATEAZ-24-R/candlesticks",
"row_type": "candle",
"venue": "kalshi",
"race_id": "SENATEAZ-24",
"market_id": "SENATEAZ-24-R",
"candidate": "Kari Lake",
"period": "daily",
"period_end": "2024-10-08T04:00:00Z",
"open": 0.14,
"high": 0.16,
"low": 0.14,
"close": 0.15,
"mean": 0.1503,
"yes_bid_open": 0.1,
"yes_bid_high": 0.15,
"yes_bid_low": 0.1,
"yes_bid_close": 0.13,
"yes_ask_open": 1.0,
"yes_ask_high": 1.0,
"yes_ask_low": 0.14,
"yes_ask_close": 0.15,
"volume": 1447.0,
"open_interest": 967.0
}
| Field | Example value | Meaning |
|---|---|---|
row_type | candle | race, candidate, candle or trade |
venue | kalshi | kalshi or polymarket |
race_id | SENATEAZ-24 | Kalshi event ticker (SENATEAZ-24) or Polymarket event id; on every row, so rows join to their race |
market_id | SENATEAZ-24-R | One candidate’s market; on candidate, candle and trade rows |
title / series / cycle / tags | — | Race rows: the race as the venue titles it, its series, election year and tags |
winner | — | Race rows: the candidate(s) whose market settled yes |
candidate / result / settlement_value / last_price | — | Candidate rows: who, yes or no, what the contract paid, the last traded price |
volume / open_interest | — | Contracts traded and outstanding (open interest from Kalshi only) |
The column most people come for is close: the last price of the day on a contract that pays $1,
so 0.15 reads as a 15% chance. Kari Lake’s first candle above closed there on 2024-10-08. Expect
blanks in two places. A Kalshi day with no trade has no open, high, low or close, but keeps its bid,
ask and open interest. Polymarket rows carry close only, because Polymarket publishes a price per
point in time and nothing else.
Step 5 — Export it
Open the Dataset tab and export to CSV, JSON, or Excel — or pull the same rows from the API, which is what you want if this is going to run on a schedule.
What it costs
Each row type has its own price: $0.0003 per candle, $0.002 per race, $0.002 per candidate and $0.0001 per trade. Marker rows (no match, truncated, blocked) are free. The Arizona Senate input above came to about $0.32. One race over its final 10 days (1 race, 2 candidates, 22 candles) costs about $0.011, which is what the QA account was charged on 2026-11-06.
Where the data comes from
This reads Kalshi + Polymarket directly. The target is Kalshi’s public trade-api/v2 (election series, events, candlesticks, trades, and its /historical archive for older markets) plus Polymarket’s gamma-api search and CLOB price history. No key, no login, no browser, no proxy by default. Every night a canary runs this actor against that live source and diffs the result against a frozen fixture — what “verified” means.
The awkward part is that a settled race does not stay in one place. Kalshi lists SENATEAZ-24 with no markets in its live tree and answers 404 for its candles there; its candles sit under /historical, with field names that differ from the live ones. Polymarket gives a whole life of daily prices in one call but hourly prices only in windows of at most 15 days.
See it used
2026 Senate Races: Kalshi Odds History and Results pulls the final month of 20 settled Senate markets for a forecast-accuracy check.
For today’s prices across every Kalshi and Polymarket market rather than one race’s past, use the Kalshi & Polymarket Prediction Market Odds Scraper.
Last updated 2026-11-06