# Kalshi Weather Markets — Odds, Brackets & Forecast (`lergassy/kalshi-weather-scraper`) Actor

Every Kalshi daily temperature market — 24 US cities, highs and lows — with per-bracket prices, fair probabilities with the exchange's overround stripped out, and the weather forecast for the exact station a market settles on next to the market's own expected temperature. No API key, no login.

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

## Pricing

from $0.70 / 1,000 brackets

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 Weather Markets** turns every daily temperature market on Kalshi into a table — 24 US cities, highs and lows — and puts a weather forecast next to each price. Every bracket comes back with its temperature band, the price, the implied probability, the fair probability with the exchange's overround stripped out, volume, open interest and the close time. No API key, no login, no browser.

![One run of Kalshi Weather Markets: each city and day with the favourite bracket, the market's expected temperature and the forecast.](https://raw.githubusercontent.com/lergassy/apify-actor-assets/main/kalshi-weather-scraper/kalshi-weather-scraper-output-table.png)

Four modes: **brackets** (one row per tradable band), **days** (one row per city and day with the whole distribution), **forecast vs market** (where the models and the crowd disagree), and **series** (what Kalshi lists right now).

### What is Kalshi Weather Markets?

Kalshi runs a temperature market for each major US city, every day: a ladder of brackets — "83° or below", "84° to 85°", "86° to 87°" — where each contract pays $1 if the day's high or low lands in that band. The prices are the crowd's probability distribution over tomorrow's weather.

This Actor reads that distribution and hands it back as data, alongside the two things you need to judge it: the forecast for the exact station the market settles on, and what that station has already recorded today.

### What makes it different

**The forecast is matched to the settlement station, not to the city.** A Kalshi market settles against one specific NWS climate report, and that station is often not where you would guess. Chicago settles at Midway, not O'Hare. Los Angeles settles at the airport by the ocean, ten degrees cooler than downtown on a hot day. One series titled "HIGHEST Temperature SATX" settles in Louisville. This Actor reads the station out of each market's own resolution rules and fetches the forecast for that point — the difference against a naive city-centre lookup ran to seven degrees on the day this was written.

**Probabilities that add up.** The prices of a bracket ladder sum to more than 1; the surplus is the exchange's overround. Every row carries both the raw `probability` and the `fairProbability` with that surplus removed, plus the `overround` itself.

**Dead days are labelled, not dressed up.** Kalshi lists city-days nobody has traded, where all six brackets sit at a fraction of a cent. Normalising those produces confident-looking probabilities out of two cents of volume. Those days come back flagged `illiquid`, with fair probabilities withheld, and are left out of the forecast mode entirely.

### What data does it return?

#### Brackets

| Field | Example |
|---|---|
| `city`, `station`, `date` | New York City · CLINYC · 2026-09-09 |
| `metric` | high · low |
| `bracket`, `floor`, `cap`, `strikeType` | 84° to 85° · 84 · 85 · between |
| `probability`, `fairProbability` | 34.0 · 32.4 (per cent) |
| `yesPrice`, `noPrice`, `bestBid`, `bestAsk`, `spread` | 0.34 · 0.66 · 0.33 · 0.35 · 0.02 |
| `volume`, `volume24h`, `openInterest` | 6,802 · … · 4,120 |
| `marketExpected`, `overround`, `illiquid` | 84.1° · 0.05 · false |
| `forecastValue`, `forecastPicksThisBracket` | 86.3 · false |
| `status`, `result`, `closeTime`, `rules`, `url` | active · empty until it settles · … |

#### Days

One row per city and day: every bracket with its probability, the `favourite` band, the market's own `marketExpected` temperature, the forecast, the gap between them, and which bracket the forecast lands in together with what the market charges for it. That last number is the useful one — a forecast pointing at a bracket the market prices at 2% is a disagreement worth reading.

#### Forecast vs market

The same rows, filtered to days where a forecast exists and the market is actually priced. For a day already under way it also carries `observedHigh` and `observedLow`: what the station has recorded so far. A model that still disagrees with a market at 2pm is usually a stale model, not an edge, and the observation is what tells you which.

### How much does it cost?

Pay per row, and only for rows you actually get:

| Event | Price |
| --- | --- |
| Bracket | $0.001 |
| Day | $0.003 |
| Forecast row | $0.004 |
| Series row | $0.0005 |

**Error rows are never charged, and there is no charge for starting a run.** Two public JSON APIs, no browser and no proxy, so platform usage is negligible.

| Job | Cost |
| --- | --- |
| Every city, highs and lows, today and tomorrow (≈290 brackets) | $0.29 |
| A daily snapshot of all cities for a month | $8.70 |
| Forecast vs market for every city, once a day for a month | $4.90 |

The other Kalshi weather Actor charges $0.001 per row plus $0.005 for every run and returns market records only. This one matches the row price, drops the start fee, and adds the forecast and the observations.

### How to use it

1. Choose **📋 What to get**: brackets, days, forecast vs market, or the series list.
2. Pick **🌡️ What kind of weather** — daily high and low are the ones traded every day.
3. Narrow to **🏙️ Cities** if you want (partial names work), and set **📅 Days ahead**.
4. Leave **🔭 Add the weather forecast** on unless you want a pure market snapshot.
5. Click **Start**, then export as JSON, CSV or Excel, or read the dataset through the API.

![The input form of Kalshi Weather Markets: mode, weather type, cities, days ahead and the forecast toggle.](https://raw.githubusercontent.com/lergassy/apify-actor-assets/main/kalshi-weather-scraper/kalshi-weather-scraper-input-form.png)

### ⬇️ Input

```json
{
  "mode": "markets",
  "metrics": ["high", "low"],
  "days": 2,
  "withForecast": true,
  "maxRows": 500
}
```

#### Where the forecast and the market disagree

```json
{ "mode": "forecast", "metrics": ["high", "low"], "days": 3 }
```

#### One city, several days

```json
{ "mode": "events", "cities": ["Chicago"], "days": 7 }
```

#### Named series only

```json
{ "mode": "markets", "seriesTickers": ["KXHIGHNY", "KXLOWTNYC"], "days": 5 }
```

### ⬆️ Output

```json
{
  "type": "bracket",
  "seriesTicker": "KXHIGHNY",
  "eventTicker": "KXHIGHNY-26SEP09",
  "marketId": "KXHIGHNY-26SEP09-B84",
  "metric": "high",
  "station": "CLINYC",
  "city": "New York City",
  "country": "US",
  "date": "2026-09-09",
  "question": "Highest temperature in New York City on Sep 9, 2026?",
  "bracket": "84° to 85°",
  "floor": 84,
  "cap": 85,
  "midpoint": 84.5,
  "probability": 34,
  "fairProbability": 32.4,
  "yesPrice": 0.34,
  "bestBid": 0.33,
  "bestAsk": 0.35,
  "volume": 6802.27,
  "openInterest": 4120.5,
  "overround": 0.05,
  "illiquid": false,
  "marketExpected": 84.1,
  "forecastValue": 86.3,
  "forecastPicksThisBracket": false,
  "closeTime": "2026-09-10T05:00:00Z",
  "url": "https://kalshi.com/markets/kxhighny",
  "scrapedAt": "2026-09-09T11:00:00.000Z"
}
```

A source that fails arrives as a `type: "error"` row with the reason, never as a silently short list.

### Use cases

#### Trading the temperature ladder

Pull every bracket with its fair probability and compare it against the forecast for the station that actually settles the market.

#### Weather desks and newsletters

One row per city and day with the crowd's full distribution — a cleaner "what does the market think it will be tomorrow" than any single number.

#### Research

Schedule the run and keep a time series of how the distribution moved as the day approached, then compare it against what the station recorded.

#### Energy and logistics

Temperature markets are a live, priced consensus for the days ahead, in the cities where load and delivery costs actually move.

#### AI agents

An agent asked "what does the market think tomorrow's high in Chicago will be" runs the days mode for one city and reads `favourite` and `marketExpected` off the row.

### 🤖 For AI Agents & LLM Apps

Compact reference for agents calling this Actor through the [Apify MCP server](https://mcp.apify.com) or the Apify API (`lergassy/kalshi-weather-scraper`).

**Purpose:** returns Kalshi's daily temperature markets as a probability distribution per city and day, with a forecast and today's observations beside them.

**Minimal input:**

```json
{ "mode": "events", "cities": ["Chicago"], "days": 3 }
```

**Behaviors an agent should know:**

- **Quote `fairProbability`**, not `probability`: the raw prices of a ladder sum to more than 100%, and the fair figure is the one that adds up.
- `marketExpected` is a fair-weighted average of bracket midpoints. When `marketExpectedIsBounded` is true, most of the money sits in an open-ended end bracket ("93° or above"), the average is capped by construction, and a gap against the forecast there is an artefact — read `forecastBracketFairProbability` instead.
- Rows flagged `illiquid` have no meaningful prices; the forecast mode drops them already.
- `station` is the NWS climate report the market settles against, and it is authoritative — the city in a series title can be wrong.
- For today's date, `observedHigh` and `observedLow` are what the station has already recorded. A forecast that disagrees with the market after those are in is usually stale.
- Temperatures are in Fahrenheit, because that is the unit Kalshi settles in.
- Both APIs are public: no key, no account, no proxy.

### Kalshi weather API without a key

Kalshi publishes open endpoints for series, events and markets, and this Actor handles the nesting, the bracket strike types and the two flavours of open-ended band. The forecast comes from Open-Meteo and the observations from the US National Weather Service, both public and both keyless.

### ❓ FAQ

#### Is this financial advice or a trading tool?

No. It reads public market data and public weather data and returns them as a table. It places no orders and holds no positions.

#### Which cities are covered?

The 24 US cities Kalshi runs daily temperature markets for, from New York, Chicago and Los Angeles to Phoenix, Seattle and New Orleans. Run the series mode to see the current list — Kalshi adds and retires series.

#### Why is the forecast sometimes far from the market?

Two honest reasons and one artefact. The models can genuinely disagree with the crowd; a model run for a day already under way can be stale while the market has seen the morning readings; and when the money sits in an open-ended end bracket, `marketExpected` understates by construction — that case is flagged.

#### Does it cover rain, snow and hurricanes?

The filters accept them and the series mode lists them, but Kalshi frequently has no open event on those series. Daily highs and lows are what trades every day.

#### How fresh are the numbers?

Live at the moment of the run. Schedule the Actor to build your own time series.

#### Can I use it with the Apify API or an MCP server?

Yes. It runs from the API and the official clients, and AI agents reach it through the Apify MCP server without extra setup.

### Your feedback

Missing a city, or a field you need? Open an issue on the **Issues** tab — every one gets answered.

### You might also like

| Actor | What it does |
|---|---|
| [Kalshi Scraper & API](https://apify.com/lergassy/kalshi-scraper) | Every Kalshi market, not just weather |
| [Polymarket Scraper & API](https://apify.com/lergassy/polymarket-scraper) | The same shape for Polymarket |
| [Prediction Markets API](https://apify.com/lergassy/prediction-markets-api) | Kalshi and Polymarket in one table |
| [Sports Betting Odds API](https://apify.com/lergassy/sports-odds-api) | Bookmaker lines, arbitrage and value bets |

### Also known as

People look for this Actor as a Kalshi weather API, KXHIGH and KXLOW data, temperature market odds, weather prediction market data, Kalshi temperature brackets and daily high temperature betting odds.

# Actor input Schema

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

<b>Brackets</b> is the raw table: every temperature band with its price. <b>Days</b> collapses them into one row per city and day with the whole distribution. <b>Forecast vs market</b> keeps only days where a weather forecast exists and shows the gap between it and the market's own expected temperature.

## `metrics` (type: `array`):

Kalshi files all of these under Climate and Weather. Daily high and low are the ones traded every day; rain, snow and hurricane series are listed but often have no open event.

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

Leave empty for every city Kalshi lists. Partial names work: <code>New York</code>, <code>Chicago</code>, <code>Phoenix</code>. 24 US settlement stations are mapped to coordinates, so the forecast compares against the exact station a market settles on.

## `days` (type: `integer`):

How far ahead to look. Kalshi opens a fresh event per city per day; the forecast covers up to 16 days.

## `withForecast` (type: `boolean`):

Fetches the Open-Meteo forecast for each city and puts it next to the market price. Turn it off for a pure market snapshot; it costs nothing either way.

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

Drop brackets that have barely traded. Far-out temperature bands often sit at a fraction of a cent with no volume at all.

## `includeSettled` (type: `boolean`):

Off by default: only days you can still trade. Turn on to see how past days resolved.

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

Skip the filters and name the series directly: <code>KXHIGHNY</code>, <code>KXLOWTEGLL</code>, <code>KXRAINDNYC</code>. Run the series mode once to see them all.

## `maxRows` (type: `integer`):

Cap on rows per run.

## Actor input object example

```json
{
  "mode": "markets",
  "metrics": [
    "high",
    "low"
  ],
  "cities": [],
  "days": 3,
  "withForecast": true,
  "minVolume": 0,
  "includeSettled": false,
  "maxRows": 500
}
```

# Actor output Schema

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

One row per bracket with the city, the day, the temperature band, its price, implied and fair probability, volume, open interest, and the forecast for that city and day. Day mode returns one row per city and day with the whole distribution; forecast mode the gap between the forecast and the market.

# 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": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("lergassy/kalshi-weather-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": [] }

# Run the Actor and wait for it to finish
run = client.actor("lergassy/kalshi-weather-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": []
}' |
apify call lergassy/kalshi-weather-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lergassy/kalshi-weather-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/9YeMkwndHKBWGh5hM/builds/35KprUHepKODWuPhb/openapi.json
