← Guides

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.

The Kalshi & Polymarket Election Odds History Scraper listing on the Apify Store
The listing on the Apify Store. Pricing and the nightly health record are both public.

Step 2 — Fill in the input

The input form for Kalshi & Polymarket Election Odds History Scraper in the Apify Console
The input form, as it appears in the Apify Console.
FieldTypeRequiredWhat it does
queriesarraynoRaces 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 [])
querystringnoOne keyword. Kept alongside ‘Keywords’ for saved tasks and API callers.
seriesTickersarraynoExact Kalshi series, e.g. SENATEAZ, GOVPARTYOR, HOUSEPA7, SENATENM. One series holds every cycle of that race (2024, 2026, 2028…). (default [])
seriesTickerstringnoOne series ticker. Kept alongside ‘Kalshi series tickers’ for saved tasks and API callers.
tagsarraynoEvery Kalshi election series carrying any of these tags: Senate, House, Governor, Primaries, US Elections, Referendums, Local, 2028, International. Broad: combine with ‘Cycle’… (default [])
venuesstringnoKalshi, Polymarket or both. Both returns the same race from each venue as separate rows with a ‘venue’ field. (default both)
cyclestringnoElection year. Kalshi’s year comes from the race ticker (SENATEAZ-24), Polymarket’s from the market’s end date. (default any)
statusstringnoSettled races (the default) carry the result and their whole history. Open races give the history so far. (default settled)
granularitystringnoOne row per day or per hour of each candidate’s odds. Hourly is 24 times the rows (and the cost). (default daily)
fromstringnoOnly candles and trades from this date (YYYY-MM-DD). Empty = from the day the market opened.
tostringnoOnly candles and trades up to this date (YYYY-MM-DD). Empty = until the market settled, or today if it is open.
includeTradesbooleannoEvery 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.
maxRacesintegernoStop after this many races from each venue. (default 10)
maxResultsintegernoA 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:

The output fields returned by Kalshi & Polymarket Election Odds History Scraper
The output view — every field the actor returns, named and typed.

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
}
FieldExample valueMeaning
row_typecandlerace, candidate, candle or trade
venuekalshikalshi or polymarket
race_idSENATEAZ-24Kalshi event ticker (SENATEAZ-24) or Polymarket event id; on every row, so rows join to their race
market_idSENATEAZ-24-ROne 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