# Kalshi Prediction Markets Scraper (`aurenic/kalshi-prediction-markets-scraper`) Actor

Scrape Kalshi prediction markets: live prices, yes/no odds, volume, open interest, order book depth and recent trades. Keyless, no API key, HTTP-only.

- **URL**: https://apify.com/aurenic/kalshi-prediction-markets-scraper.md
- **Developed by:** [Aurenic](https://apify.com/aurenic) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.40 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Kalshi Prediction Markets Scraper

Scrape Kalshi prediction markets for live prices, yes/no odds, volume, open interest, order book depth and recent trades — keyless, no API key, HTTP-only.

### What does Kalshi Prediction Markets Scraper do?

Kalshi is the CFTC-regulated prediction market exchange where contracts settle on real-world events: elections, economic data, crypto prices, weather, sports and more. This actor reads Kalshi's public REST API and returns structured records. It supports three modes: a filtered market list across every open series, a per-ticker detail pull with live order book and recent trades, and an events view that nests each event's markets under one row.

### Output fields

**Market record (markets and marketDetail modes)**

| Field | Type | Description |
|---|---|---|
| ticker | string | Kalshi market ticker, e.g. KXBTCD-26NOV15-T100000 |
| event\_ticker | string | Parent event ticker |
| series\_ticker | string | Parent series ticker |
| title | string | Market question |
| subtitle | string | Contract subtitle |
| category | string | Politics, Economics, Crypto, Sports, Climate, … |
| status | string | open, closed or settled |
| market\_type | string | binary or scalar |
| yes\_bid | number | Best yes bid in cents |
| yes\_ask | number | Best yes ask in cents |
| no\_bid | number | Best no bid in cents |
| no\_ask | number | Best no ask in cents |
| last\_price | number | Last traded price in cents |
| previous\_yes\_bid | number | Prior session yes bid |
| previous\_yes\_ask | number | Prior session yes ask |
| previous\_price | number | Prior session price |
| volume | integer | Lifetime contracts traded |
| volume\_24h | integer | Contracts traded in the last 24 hours |
| open\_interest | integer | Contracts currently open |
| liquidity | integer | Posted liquidity in cents |
| open\_time | string | ISO timestamp |
| close\_time | string | ISO timestamp |
| expiration\_time | string | ISO timestamp |
| settlement\_value | number | Final settlement value if settled |
| result | string | yes or no if settled |
| can\_close\_early | boolean | Early-close flag |
| rules\_primary | string | Primary settlement rules |
| rules\_secondary | string | Secondary settlement rules |
| orderbook | object | Live yes/no book (marketDetail with includeOrderbook) |
| recent\_trades | array | Last 50 trades (marketDetail with includeTrades) |
| scraped\_at | string | ISO timestamp |

**Event record (events mode)**

| Field | Type | Description |
|---|---|---|
| event\_ticker | string | Event identifier |
| series\_ticker | string | Parent series |
| title | string | Event title |
| sub\_title | string | Event subtitle |
| category | string | Category |
| mutually\_exclusive | boolean | Whether markets are mutually exclusive |
| strike\_period | string | Strike period label |
| markets | array | Nested market records |
| market\_count | integer | Number of nested markets |
| scraped\_at | string | ISO timestamp |

### Who is it for?

- **Prediction-market traders** building dashboards and alerting on price moves
- **Quantitative researchers** studying market efficiency, liquidity and calibration
- **Financial analysts** tracking implied probabilities for elections, CPI prints and Fed decisions
- **Sports bettors** comparing Kalshi lines against traditional sportsbooks
- **Data teams** building event-probability feeds for newsrooms, funds and AI agents
- **Arbitrage desks** comparing Kalshi prices against Polymarket, PredictIt and sportsbook lines

### Pricing

**Pay per result: $0.40 per 1,000 records.**

You are charged only for records actually written to the dataset. A run that returns nothing is not billed.

### How to use it

1. Open the actor in Apify Console.
2. Choose a mode: **Markets** for a filtered list, **Market detail** for specific tickers, **Events** for event-grouped output.
3. For markets mode, set status, series ticker, event ticker, category and volume/OI floors.
4. For marketDetail mode, paste one or more tickers and toggle order book and trades.
5. Optionally cap max results to control cost.
6. Click **Start** and export as JSON, CSV or Excel.

### Output example

```json
{
  "ticker": "KXBTCD-26NOV15-T100000",
  "event_ticker": "KXBTCD-26NOV15",
  "series_ticker": "KXBTCD",
  "title": "Bitcoin price on Nov 15, 2026?",
  "subtitle": "$100,000 or above",
  "category": "Crypto",
  "status": "open",
  "market_type": "binary",
  "yes_bid": 42,
  "yes_ask": 44,
  "no_bid": 56,
  "no_ask": 58,
  "last_price": 43,
  "volume": 18420,
  "volume_24h": 3120,
  "open_interest": 8740,
  "liquidity": 142000,
  "open_time": "2026-09-01T00:00:00Z",
  "close_time": "2026-11-15T15:00:00Z",
  "expiration_time": "2026-11-15T15:00:00Z",
  "result": null,
  "scraped_at": "2026-09-28T12:00:00.000Z"
}
```

### Technical details

- **Stack:** Node.js 24, `apify` SDK, native `fetch`. No browser, no proxy, no TLS impersonation needed.
- **API:** Kalshi's public REST API at `https://api.elections.kalshi.com/trade-api/v2`. Market, event, order book and trade endpoints all answer without an API key. Read rate limit is roughly 20 requests per second on the entry tier.
- **Pagination:** Cursor-based via the `cursor` field, 200 rows per page, up to 100 pages.
- **Retries:** 429 and 5xx responses are retried up to three times with backoff. 404s return null. Other HTTP errors fail fast.
- **Order book:** Optional depth-10 snapshot per ticker.
- **Trades:** Optional last-50 trade tape per ticker.

### Known limits

- **Kalshi floods the /markets endpoint with zero-volume parlay markets.** A 2026-09 changelog from a competing actor reported over 8,000 zero-volume parlay markets polluting `/markets`. This actor exposes `minVolume` and `minOpenInterest` filters to strip them out. Set `minVolume` to 1 or higher to skip the noise.
- **Read rate limit is roughly 20 requests per second.** The actor paces itself at 250 ms between calls, which keeps it safely under that ceiling even with order book and trade fetches enabled.
- **Settlement value and result are null until the market resolves.** Open markets carry neither field.
- **Order book depth is capped at 10 levels per side.** Deeper books are not exposed by the public endpoint without authentication.
- **Historical markets older than the live window are not covered.** Kalshi's historical endpoints sit under a separate path and are not part of this actor.

### FAQ

**Do I need a Kalshi account or API key?**
No. Every endpoint this actor calls is public and answers without authentication.

**Why is minVolume useful?**
Kalshi creates thousands of zero-volume parlay markets that pollute the markets list. Set `minVolume` to 1 or `minOpenInterest` to 1 to strip them and keep only markets that actually trade.

**How often does Kalshi update prices?**
Continuously during market hours. Prediction-market prices move on news and order flow. Schedule the actor every few minutes if you need a live feed.

**Does this cover Kalshi's sports markets?**
Yes. Sports markets appear under the Sports category. Use the `category` filter or a series ticker to isolate them.

**Can I get the full order book?**
The public order book endpoint returns 10 levels per side. Deeper books require an authenticated session, which this actor does not use.

**What is the difference between markets and events mode?**
Markets mode returns one flat row per contract, best for time-series and screening. Events mode returns one row per event with its markets nested, best for a clean event-level view.

### Support

Open an issue on the Actor's page for bugs or feature requests.

### Changelog

#### 0.1 — 2026-09-28

- Initial build. Keyless extraction of Kalshi prediction-market data from the public REST API.
- Three modes: markets list, market detail with order book and trades, events with nested markets.
- Filters: status, series ticker, event ticker, category, minimum volume, minimum open interest.
- Cursor-based pagination at 200 rows per page.
- Optional order book (depth 10) and last-50 trade tape per market.
- Retries on 429 and 5xx with backoff; 404 returns null; other errors fail fast.
- No proxy, no browser, no API key.

# Actor input Schema

## `mode` (type: `string`):

What to scrape. Markets lists every market matching your filters. MarketDetail pulls one ticker with full order book and recent trades. Events lists events with their nested markets.

## `marketTickers` (type: `array`):

For marketDetail mode: one or more Kalshi market tickers. Example: KXBTCD-26NOV15-T100000.

## `status` (type: `string`):

Filter markets by lifecycle status.

## `seriesTicker` (type: `string`):

Restrict to one series, e.g. KXBTCD for Bitcoin daily. Leave empty for all series.

## `eventTicker` (type: `string`):

Restrict to one event. Leave empty for all events.

## `category` (type: `string`):

Filter markets by category, e.g. Politics, Economics, Crypto, Sports, Climate. Leave empty for all categories.

## `minVolume` (type: `integer`):

Drop markets with total volume below this number. Leave at 0 to keep everything.

## `minOpenInterest` (type: `integer`):

Drop markets with open interest below this number. Leave empty to keep everything.

## `maxResults` (type: `integer`):

Cap the number of records written. Leave empty for as many as the API returns.

## `includeOrderbook` (type: `boolean`):

Attach the live yes/no order book to each market detail row.

## `includeTrades` (type: `boolean`):

Attach the most recent trades to each market detail row.

## `excludeParlays` (type: `boolean`):

Exclude Kalshi's auto-generated multivariate parlay combos at the API level (mve\_filter=exclude). Strongly recommended — the raw /markets feed is ~99% parlay noise.

## Actor input object example

```json
{
  "mode": "markets",
  "marketTickers": [
    "KXBTCD-26NOV15-T100000"
  ],
  "status": "open",
  "seriesTicker": "",
  "eventTicker": "",
  "category": "",
  "minVolume": 0,
  "minOpenInterest": 0,
  "maxResults": 200,
  "includeOrderbook": true,
  "includeTrades": true,
  "excludeParlays": true
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("aurenic/kalshi-prediction-markets-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("aurenic/kalshi-prediction-markets-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call aurenic/kalshi-prediction-markets-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,aurenic/kalshi-prediction-markets-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Gz1Asd97EtvWBphKt/builds/tBJcMgz7HFW4aec3a/openapi.json
