# Kalshi Scraper (`mlg14/kalshi-scraper`) Actor

Collect live and settled weather markets, including temperature brackets, rain contracts, prices, volume, settlement values, and station IDs.

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

## Pricing

$0.80 / 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 Scraper

Scrape Kalshi weather markets into a flat dataset of daily temperature brackets and rain contracts. Export live prices, volume, optional order books and trades, and settled results to JSON, CSV, or Excel. The actor reads public market data and does not place orders or require an account.

### What data can you extract from Kalshi?

Each dataset row represents one contract, not one event. A daily high-temperature event can contain several mutually exclusive brackets, each with its own ticker, price, volume, and result. A daily rain event contains one yes/no contract per city. Monthly rain events contain several rainfall thresholds. Keeping one row per contract lets you compare prices within an event, follow individual tickers over time, and join settled outcomes to weather observations.

| Field | Description | Example |
|---|---|---|
| ticker | Unique contract identifier | KXHIGHCHI-26SEP27-T74 |
| event_ticker | Identifier shared by an event's contracts | KXHIGHCHI-26SEP27 |
| city | City associated with the contract | Chicago |
| station_id | Station identified in the rule, or the series' usual station | KMDW |
| series_ticker | Recurring market series | KXHIGHCHI |
| series_type | Daily high, daily low, daily rain, or monthly rain | KXHIGH |
| bracket_label | Readable temperature range or rainfall threshold | 75° or above |
| strike_type | Comparison used for settlement | greater |
| floor_strike | Lower numerical boundary, when supplied | 74 |
| cap_strike | Upper numerical boundary, when supplied | null |
| status | Current contract state | active |
| result | Final yes or no, when settled | null |
| settlement_temp_f | Official settled temperature in °F, when supplied | null |
| settlement_time | Finalization timestamp | null |
| open_time | Contract opening timestamp | 2026-09-26T14:00:00Z |
| close_time | Contract closing timestamp | 2026-09-28T06:00:00Z |
| yes_bid | Best bid for YES, dollars per contract | 0.02 |
| yes_ask | Best ask for YES, dollars per contract | 0.03 |
| last_price | Most recent YES trade price | 0.02 |
| volume | Total number of contracts traded | 329.55 |
| open_interest | Number of open contracts | 329.55 |
| liquidity | Resting liquidity in dollars | 0 |
| date | Weather date; YYYY-MM for monthly rain | 2026-09-27 |
| implied_probability | Bid/ask midpoint, or last trade for an empty book | 0.025 |
| spread | Ask minus bid; empty if the book is empty | 0.01 |
| volume_24h | Contracts traded during the previous 24 hours | 329.55 |
| market_url | Public event page | https://kalshi.com/markets/kxhighchi/kxhighchi-26sep27 |
| settlement_precip_in | Official settled rainfall in inches, when supplied | null |
| title | Market question | Will the maximum temperature be >74° on Sep 27, 2026? |
| updated_at | Last market update timestamp | 2026-09-26T14:00:01.231343Z |
| trades | Up to 1,000 recent fills, only when enabled | Array of fills |
| orderbook | Current YES and NO bid levels, only when enabled | Object of price/size levels |

Prices are dollars per one-dollar contract. For example, a yes ask of 0.03 means an ask of three cents. Volumes and open interest may have decimals because contracts can be fractional. The implied probability is a price-based indicator, not a calibrated weather forecast. A null spread means the current book has no useful bid/ask pair.

The station identifier is useful for comparing contracts to observations. Temperature and rain contracts in the same city can use different stations. The actor reads a station code from each rule when one is present, then uses the usual station for that series when the rule does not contain a code. Check the full market rule before using a station identifier for settlement-sensitive work.

### How to scrape Kalshi

1. Enter one or more cities. Use \["all"] to cover every supported city.
2. Choose a series: temperature highs and lows, rain, or all weather families.
3. Choose live, settled, or both modes.
4. Set maxItems to control dataset size. For history, set lookbackDays or an exact dateFrom and dateTo.
5. Run the actor and download the default dataset as JSON, CSV, or Excel.

A small live run usually completes quickly because each temperature series needs one market-list request. Settled history can take longer as it may require several pages of archived contracts. Enabling trades or order books adds a request per eligible contract, so try those flags with a small result limit first.

### Input

| Name | Type | Default | Description |
|---|---|---|---|
| cities | Array of strings | \["NYC"] | City names, codes, aliases, station codes, or \["all"]. |
| seriesType | String | both | KXHIGH, KXLOW, both, KXRAIN, KXRAINM, rain, or all. |
| mode | String | live | live, settled, or both. |
| lookbackDays | Integer | 30 | Settled market dates when dateFrom is empty; 1–365. |
| dateFrom | String | Empty | Inclusive first market date; YYYY-MM-DD, YYYYMMDD, today, tomorrow, or yesterday. |
| dateTo | String | Empty | Inclusive last market date in the same formats. |
| maxItems | Integer | 100 | Maximum rows; 0 removes this cap. |
| includeTrades | Boolean | false | Add up to 1,000 recent fills per row. |
| includeOrderbook | Boolean | false | Add the current YES and NO bid levels for active contracts. |
| proxyConfiguration | Object | Enabled | Network proxy configuration. |

A live run across two cities uses:

```
{
  "cities": ["NYC", "Chicago"],
  "seriesType": "both",
  "mode": "live",
  "maxItems": 100
}
```

To retrieve a week of settled New York City highs, set mode to settled, seriesType to KXHIGH, dateFrom to 2026-07-20, and dateTo to 2026-07-26. That window is in the historical archive, so it demonstrates that settled history is not limited to the current market list. The date range refers to the weather date encoded in the event ticker. It is not the UTC close date, which may fall on the next day.

City aliases include NYC, Chicago, Philly, LA, SF, and DFW. A supported temperature series ticker also selects its city. The actor rejects an input with no recognized city rather than silently returning another city's data. When cities is \["all"], temperature contracts cover 24 mapped cities; the daily rain series also includes rain-only cities such as Pittsburgh, Milwaukee, and Providence. Monthly rain coverage follows the listed series and can differ from daily rain coverage.

### Output example

This row came from a successful 48-row live run on September 26, 2026. The input selected New York City and Chicago with both temperature series. Optional trades and orderbook keys were absent because their flags were off.

```
{
  "ticker": "KXHIGHCHI-26SEP27-T74",
  "event_ticker": "KXHIGHCHI-26SEP27",
  "city": "Chicago",
  "station_id": "KMDW",
  "series_ticker": "KXHIGHCHI",
  "series_type": "KXHIGH",
  "bracket_label": "75° or above",
  "strike_type": "greater",
  "floor_strike": 74,
  "cap_strike": null,
  "status": "active",
  "result": null,
  "settlement_temp_f": null,
  "settlement_time": null,
  "open_time": "2026-09-26T14:00:00Z",
  "close_time": "2026-09-28T06:00:00Z",
  "yes_bid": 0.02,
  "yes_ask": 0.03,
  "last_price": 0.02,
  "volume": 329.55,
  "open_interest": 329.55,
  "liquidity": 0,
  "date": "2026-09-27",
  "implied_probability": 0.025,
  "spread": 0.01,
  "volume_24h": 329.55,
  "market_url": "https://kalshi.com/markets/kxhighchi/kxhighchi-26sep27",
  "settlement_precip_in": null,
  "title": "Will the maximum temperature be >74° on Sep 27, 2026?",
  "updated_at": "2026-09-26T14:00:01.231343Z"
}
```

A separate archive-window test returned 40 finalized high-temperature contracts for July 20–26, 2026. Every row had a ticker, city, date, station, result, settlement timestamp, and settled temperature. A finalized row can still have a missing settled temperature in other periods when the source leaves the official value empty; the result continues to identify whether that contract won.

### Use cases

- **Market monitoring:** Track the YES bid, YES ask, spread, and 24-hour volume for a city's current high-temperature brackets. Repeated scheduled runs show how contract prices move as a weather date approaches.
- **Weather-market backtesting:** Collect finalized bracket outcomes with their weather dates and station identifiers. Join them to observations and compare how prices related to eventual outcomes.
- **Rain-contract research:** Compare daily rain outcomes and monthly rainfall thresholds across cities. Monthly rows use YYYY-MM so they can be grouped by month.
- **Liquidity screening:** Filter rows by volume, open interest, liquidity, and spread to identify contracts with meaningful activity.
- **Event reconstruction:** Group records by event_ticker to inspect all temperature brackets in one daily event. The market ticker remains unique for each bracket.
- **Historical reporting:** Build a table of city, station, market date, settlement value, and result for a known period, including dates whose markets have moved to the archive.

The actor reads market data only. Prices can change between collection and use, and a dataset is a snapshot of what the source returned during that run. Use updated_at to identify the source update timestamp; the dataset itself does not stream changes.

### How much does it cost to scrape Kalshi?

The configured result price is **$0.0008 per market row**, or **$0.80 per 1,000 rows**. The actor pushes one row per contract, so a twelve-bracket high-temperature event counts as twelve results. A maxItems setting caps result charges: maxItems of 100 means no more than $0.08 in result events. Other platform usage, if applicable to your plan, is separate from these result charges.

| Example | Rows | Result charge |
|---|---:|---:|
| Tested two-city live temperature run | 48 | $0.0384 |
| Tested archive window capped at 40 rows | 40 | $0.0320 |
| Large pull capped at 1,000 rows | 1,000 | $0.80 |

These are arithmetic examples using the configured per-row price, not promises about future market counts. The number of active contracts changes with listings and dates. Optional trade and order-book calls do not add result events of their own, but can increase run time and platform usage. The run charge limit, when configured, is respected as results are pushed.

### Tips for best results

Start with a city and the default both temperature setting to confirm the current contract layout. If you only need a daily high or low, choose its individual series to avoid collecting the other side. For rain, KXRAIN returns daily yes/no city contracts, while KXRAINM returns monthly threshold contracts. The rain choice includes both; all includes temperature and rain families for selected cities.

Use dateFrom and dateTo for a precise historical window. A seven-day settled window is usually more focused than requesting a full year and discarding most rows later. If dateFrom is absent, lookbackDays supplies the start date for settled mode. Relative date words use the US Eastern calendar date, matching the market-day convention. A monthly rain market is compared by the first day of its month for filtering, while its output date remains YYYY-MM.

Keep maxItems modest when enabling includeTrades or includeOrderbook. Each extra field requires individual market requests. Trades are recent fills returned by the public endpoint, so they are not a complete audit trail for every historical market. For settled contracts, the order book is an empty object of YES and NO bid levels, since there is no active book. If an optional request fails, its key is present with null, and the market row is retained.

For a broad city comparison, \["all"] works without entering every name. Output remains one contract per row, and the actor stops once it reaches maxItems or the run charge limit. To ensure every city is represented, remove the item cap or run smaller city groups; a cap can be reached before later series are visited.

### Limits

The actor uses the public market-data interface. It does not access private account data, place orders, or provide a trading signal. It covers mapped daily temperature and rain series and mapped monthly rain series, rather than every topic on the site. Newly listed cities or series may require a mapping update. A monthly rain series may be listed but have no active contracts, in which case it contributes no live rows.

Current and older finalized contracts reside in separate source tiers. The actor checks the published cutoff and reads the historical tier for windows that may reach it. Archived pages arrive from newer to older contracts; paging stops after passing the requested start date. Very old or broad windows can still take longer because the archive must be paged. If one series fails after retries, other series can still return data; the failed series is named in the run log. If every requested data source fails, the run fails rather than reporting an empty success.

Some older contracts have no official settled temperature or rainfall value. Such rows can still have a final yes or no result, which tells you the contract outcome. Rules may identify a station by code; otherwise the actor uses a usual series station, which may not capture a historical rule change. Use the contract's public page for any decision that depends on exact settlement wording. Bid and ask are snapshots and can be empty for finalized markets. The optional trade list is limited to the source's recent fills, not an exhaustive history.

### Automated workflows

A connected client can run this actor with structured input and read the resulting dataset. Examples: “Get active high-temperature brackets for Chicago, limited to 50 rows” and “Get finalized New York City daily-high contracts from July 20 through July 26, including their settlement values.” Set maxItems in automated calls to keep result volume predictable. Field names and date formats are stable across live and settled modes, while fields that are not applicable remain null.

### FAQ

#### Is this public data, and can I use it?

The actor reads publicly accessible market data without signing in. You are responsible for using exported data in line with applicable terms, law, and rules governing your downstream use. It does not include personal account information or trading functionality.

#### Do I need to configure a proxy?

The default proxy configuration is set for hosted runs. Most users can leave it alone. Temporary limits or network blocks may cause retries and slower collection. If a series remains unavailable, its failure appears in the run log.

#### How fast is a run?

The tested 48-row live run finished in roughly ten seconds of actor execution. The tested archive-window run took longer because it retrieved a large historical page. Runtime depends on the number of series, archive pages, optional per-market requests, and source response time.

#### Can I schedule and monitor it?

Yes. Schedule repeated live runs to collect snapshots, and use run status plus dataset items to monitor delivery. Since one row is one contract, a scheduled history table should use ticker and collection time together if you need several observations of the same market.

#### Can I export to a spreadsheet?

Yes. Download the default dataset as CSV or Excel, or retrieve it through the platform API. Price and quantity fields are numeric, so they can be filtered, graphed, or joined to other tables after export.

#### Why is a settlement field empty?

Live markets have no final result. Some finalized archive records also lack the official measurement even though their YES/NO result is present. Rainfall and temperature settlement fields are mutually exclusive, so the field for the other weather family stays empty.

#### Why do Chicago temperature and rain records have different stations?

A city's markets can use separate settlement stations by contract type, and rules can change over time. The station in each row comes from its rule when a code is present. Check the individual rule for settlement-sensitive work.

### Integrations

Use the dataset through the platform API, webhooks, scheduled runs, or workflow connections. JSON works well for applications and analysis scripts; CSV and Excel suit spreadsheet review. Keep ticker, event_ticker, date, and station_id when joining snapshots or settled results to external weather data.

### Support

Open an issue on the Issues tab; we reply within 24 hours and add fields on request.

# Actor input Schema

## `cities` (type: `array`):

City names or codes such as NYC, Chicago, Miami, or all. Temperature markets cover 24 cities; daily rain also covers several more.

## `seriesType` (type: `string`):

Choose daily high, daily low, daily rain, monthly rain, both temperature series, both rain series, or all four families.

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

Live contracts, finalized contracts with results, or both. Settled mode includes archived markets within the date window.

## `lookbackDays` (type: `integer`):

How many market dates to include in settled mode when dateFrom is empty. The archive is included when needed.

## `dateFrom` (type: `string`):

Optional first market date, inclusive. Use YYYY-MM-DD, YYYYMMDD, today, tomorrow or yesterday.

## `dateTo` (type: `string`):

Optional last market date, inclusive. Use YYYY-MM-DD, YYYYMMDD, today, tomorrow or yesterday.

## `maxItems` (type: `integer`):

Stop after this many market records. Zero means no item cap; the run charge limit still applies.

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

Add up to 1,000 recent trades per market. Adds one request per market and can take longer.

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

Add bid levels for active markets. Adds one request per active market; settled markets have empty books.

## `proxyConfiguration` (type: `object`):

Network proxy configuration for market-data requests.

## Actor input object example

```json
{
  "cities": [
    "NYC"
  ],
  "seriesType": "both",
  "mode": "live",
  "lookbackDays": 30,
  "maxItems": 100,
  "includeTrades": false,
  "includeOrderbook": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `markets` (type: `string`):

Live and settled market records in the default dataset.

# 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 = {
    "cities": [
        "NYC"
    ],
    "seriesType": "both",
    "mode": "live"
};

// Run the Actor and wait for it to finish
const run = await client.actor("mlg14/kalshi-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 = {
    "cities": ["NYC"],
    "seriesType": "both",
    "mode": "live",
}

# Run the Actor and wait for it to finish
run = client.actor("mlg14/kalshi-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 '{
  "cities": [
    "NYC"
  ],
  "seriesType": "both",
  "mode": "live"
}' |
apify call mlg14/kalshi-scraper --silent --output-dataset

```

## MCP server setup

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