# Kalshi Markets Scraper – Odds, Volume & Order Books (`rowfeed/kalshi-markets-scraper`) Actor

Extract Kalshi prediction markets: yes/no prices, volume, open interest, close times and optional order books. Filter by series, event, category or status. Clean JSON for traders, researchers and AI agents.

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

## Pricing

from $1.00 / 1,000 markets

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Kalshi Markets Scraper – Odds, Volume & Order Books

Get Kalshi prediction-market data as clean JSON rows: every market's YES/NO price, bid and ask, volume, open interest, close time and, on request, the live order book.
Built for traders, researchers, AI agents and dashboards that need Kalshi odds without a login, an API key or a headless browser.
Plain HTTPS calls to Kalshi's public API with retries and a silent-failure check, so a scheduled run keeps working when the exchange hiccups.

### What you get

- **Every market as one row** – ticker, title, YES/NO last price, bid and ask, lifetime and 24 h volume, open interest, liquidity, open/close/expiration times, rules and result, plus `series_ticker`, `category` (Sports, Politics, Climate and Weather, Crypto, Economics…) and a link to the market page.
- **Order books on demand** – the top N price levels on both the YES and the NO side as `[price, size]` pairs in dollars, read at the same moment as the row.
- **Filters that match real questions** – one series (`KXHIGHNY` for NYC daily highs, `KXNFLGAME` for NFL games), one event, a category, a market status (open, closed, settled, unopened, all), a minimum volume and a sort order, with a hard cap on rows so the cost of a run is known up front. A default run returns the 200 markets with the highest 24 h volume, not whatever the API happens to list first.

### Sample row

One open NYC-temperature market scraped with `includeOrderbook: true` and `orderbookDepth: 3`. The raw Kalshi fields (`rules_secondary`, `price_ranges`, `*_dollars`, `*_fp`, …) are trimmed here but present in every row.

```json
{
  "ticker": "KXHIGHNY-26SEP09-T84",
  "event_ticker": "KXHIGHNY-26SEP09",
  "series_ticker": "KXHIGHNY",
  "category": "Climate and Weather",
  "title": "Will the maximum temperature be <84° on Sep 9, 2026?",
  "yes_sub_title": "83° or below",
  "no_sub_title": "83° or below",
  "status": "active",
  "market_type": "binary",
  "yes_price": 0.7,
  "yes_bid": 0.68,
  "yes_ask": 0.69,
  "no_bid": 0.31,
  "no_ask": 0.32,
  "volume": 7769.32,
  "volume_24h": 7769.32,
  "open_interest": 5758.8,
  "liquidity": 0.0,
  "open_time": "2026-09-08T14:00:00Z",
  "close_time": "2026-09-10T05:00:00Z",
  "expiration_time": "2026-09-16T14:00:00Z",
  "result": "",
  "url": "https://kalshi.com/markets/kxhighny",
  "scraped_at": "2026-09-09T10:32:35+00:00",
  "strike_type": "less",
  "cap_strike": 84,
  "rules_primary": "If the maximum temperature recorded at New York City (CLINYC) for Sep 9, 2026, is less than 84° fahrenheit according to The Weather Company, then the market resolves to Yes.",
  "orderbook": {
    "yes": [[0.66, 35.0], [0.67, 34.0], [0.68, 15.0]],
    "no": [[0.29, 42.0], [0.3, 25.0], [0.31, 40.0]]
  }
}
```

### Filters

| Input | Default | What it does |
|---|---|---|
| `seriesTickers` | `[]` | Series to scrape, e.g. `["KXHIGHNY", "KXNFLGAME"]`. The series ticker is the first dash-separated part of a market ticker. Empty = all series. |
| `eventTickers` | `[]` | Specific events, e.g. `["KXHIGHNY-26SEP09"]`. Used together with series tickers when both are set. |
| `categories` | `[]` | Keep only markets whose series category contains one of these words (case-insensitive). `["Weather"]` matches "Climate and Weather". |
| `status` | `open` | `open`, `closed`, `settled`, `unopened` or `all`. |
| `minVolume` | `0` | Skip markets whose lifetime volume (contracts traded) is below this number. |
| `sortBy` | `volume_24h` | Row order: `volume_24h`, `volume` or `open_interest` (highest first), `close_time` (soonest first), or `none` for Kalshi's API order. |
| `maxMarkets` | `200` | Keep this many rows after filtering and sorting. |
| `includeOrderbook` | `false` | Fetch the YES/NO order book for every row. |
| `orderbookDepth` | `10` | Price levels per side (1–100). |

Runs without a series or event ticker skip Kalshi's multivariate combination markets (`KXMVECROSSCATEGORY…`, tens of thousands of near-identical parlay shards). Pass that series ticker explicitly if you want them.

Kalshi's API lists markets in no useful order (the first pages are mostly zero-volume micro-markets), so a run without a series, event or category filter fetches a pool of up to 3,000 markets, applies `minVolume`, sorts by `sortBy` and keeps `maxMarkets` rows. With filters, the volume floor and the sort order apply to the markets fetched for those filters. Only the rows you keep are charged.

### Pricing

Pay per event, no subscription: **$1 per 1,000 markets** and **$2 per 1,000 order books**. A default run (200 open markets, no order books) costs $0.20; 200 markets with order books cost $0.60. Set a maximum charge on the run and the Actor stops cleanly when it is reached, charging only for rows that were actually saved.

### Use it from your tools

- **API and SDKs** – call it via the Apify API or the official Python/JavaScript clients: one call to start the run, one to fetch the dataset as JSON or CSV.
- **Schedules** – run it hourly or daily inside Apify and push new rows to Google Sheets, a webhook or your own storage automatically.
- **n8n, Make and Zapier** – trigger runs and pipe markets into a workflow through Apify's integration for each.
- **AI agents and MCP** – this Actor is eligible for agentic use via Apify's MCP server and supports pay-per-event pricing, so an agent can call it mid-task and pay only per market it actually reads.
- **Webhooks** – fire on run finished to kick off the next step in a pipeline as soon as fresh markets land.

### Details

- **Source**: Kalshi's public trade API v2 (`api.elections.kalshi.com/trade-api/v2`). No authentication, no proxies, no browser, no personal data.
- **Freshness**: prices are read at scrape time; `scraped_at` is the UTC timestamp of the run. `yes_price` is the last trade in dollars (0–1, i.e. the implied probability) and stays `0` until a market's first trade, so use `yes_bid` / `yes_ask` for untraded markets. Kalshi reports open markets as `active` in the `status` column.
- **Reliability**: 429 and 5xx responses are retried with exponential backoff (5 tries), a 200 without the expected data counts as a failure, and one bad ticker never stops the run: it becomes an error row (`ticker`, `error`, `errorMessage`) and the rest continues. A run fails only when it produced no rows *and* hit errors; a filter with no matching markets (e.g. a series with nothing open) is a successful, empty run.
- **Run stats**: the `STATS` record in the run's key-value store holds request and error counts per category (`network`, `rate_limit`, `blocked`, `not_found`, `other`).
- **Speed**: a default run (3,000 markets pooled, 200 kept) finishes in about 15 seconds. 1,000 markets is a single API call; order books add roughly half a second per market.
- **Output**: one dataset row per market with the columns above first and every raw Kalshi field after them. The Overview table shows title, YES price, volume, open interest, close time and ticker. Export as JSON, CSV or Excel, fetch through the Apify API, or schedule runs and pipe them into Google Sheets, Make, Zapier or your own code.

# Actor input Schema

## `seriesTickers` (type: `array`):

Kalshi series to scrape, e.g. KXHIGHNY (NYC daily high temperature) or KXNFLGAME. The series ticker is the first dash-separated part of any market ticker. Leave empty to scrape across all series.

## `eventTickers` (type: `array`):

Specific events to scrape, e.g. KXHIGHNY-26SEP09. An event groups the markets for one date, game or question. Used together with series tickers when both are set.

## `categories` (type: `array`):

Keep only markets whose series category contains one of these words (case-insensitive). Kalshi categories include Sports, Entertainment, Politics, Elections, Financials, Economics, Climate and Weather, Science and Technology, Crypto, Companies, World, Health, Commodities. "Weather" matches "Climate and Weather".

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

Which markets to return: open (trading now), closed (trading ended, not yet settled), settled (resolved with a result), unopened (announced, not yet trading), or all.

## `minVolume` (type: `number`):

Skip markets whose lifetime volume (contracts traded) is below this number. 0 keeps every market, including ones that have never traded.

## `sortBy` (type: `string`):

Order of the rows: 24 h volume, lifetime volume or open interest (highest first), close time (soonest first), or none for Kalshi's API order. Without a series, event or category filter the Actor ranks a pool of up to 3,000 markets, so the default run returns the most active markets instead of whatever the API lists first.

## `maxMarkets` (type: `integer`):

Keep this many market rows after filtering and sorting. Each row is one `market` event ($1 per 1,000).

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

Fetch the live YES/NO order book for every market. One extra request and one `orderbook` event ($2 per 1,000) per market.

## `orderbookDepth` (type: `integer`):

Number of price levels per side to include when the order book is on.

## Actor input object example

```json
{
  "seriesTickers": [
    "KXHIGHNY",
    "KXNFLGAME"
  ],
  "eventTickers": [
    "KXHIGHNY-26SEP09"
  ],
  "categories": [
    "Weather",
    "Politics"
  ],
  "status": "open",
  "minVolume": 0,
  "sortBy": "volume_24h",
  "maxMarkets": 200,
  "includeOrderbook": false,
  "orderbookDepth": 10
}
```

# Actor output Schema

## `results` (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("rowfeed/kalshi-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("rowfeed/kalshi-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 rowfeed/kalshi-markets-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rowfeed/kalshi-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/YMxX1Cz8eBW9A1Xw7/builds/wKB58xIke3hsU9KDh/openapi.json
