# Polymarket Weather Markets Scraper - Daily High/Low Temp Odds (`neverempty/polymarket-weather-markets`) Actor

For weather traders and forecasters: every Polymarket daily high/low temperature bracket with Yes price, live bid/ask, volume, city, date, station and result. 3,124 brackets in 51 cities on 2026-09-21. Compare the odds with Kalshi or your forecast in one table.

- **URL**: https://apify.com/neverempty/polymarket-weather-markets.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** Developer tools, Automation, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.92 / 1,000 market returneds

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?

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

## Polymarket Weather Markets Scraper - Daily High/Low Temp Odds

For weather traders, forecasters and prediction-market researchers: every Polymarket "Highest temperature in <city> on <date>" and "Lowest temperature in <city> on <date>" market, one row per temperature bracket, with the Yes price, the yes bid and ask from the live order book, last trade, volume, liquidity, city, date, unit, bracket bounds, the weather station named in the rules and, for finished markets, the result. On 2026-09-21 Polymarket listed 3,124 current brackets in 284 events across 51 cities. You get the whole temperature ladder of every city in one table, ready to compare with your forecast or with Kalshi, without clicking through 284 event pages.

It reads Polymarket's public market-data API (`gamma-api.polymarket.com`) and its public order-book API (`clob.polymarket.com`). No login, no API key, no proxy, no wallet.

Export as JSON, CSV or Excel.

### Why this Actor

- **Live bid and ask, not the cached ones.** Polymarket's market data carries a best bid and ask that can lag the order book. On 2026-09-21 we read both at the same moment for the 22 NYC brackets of September 22: 4 differed, and for "51°F or below" the market data said the Yes ask was 0.02 while the order book said 0.11. This Actor reads the order book in batches of 200 markets and says where each price came from (`pricesFrom`).
- **Stale markets are left out.** Polymarket still lists some events from May 2026 as open, without prices. Events whose end date is more than 3 days past are not requested, and are checked again on arrival: if Polymarket still sends one, it is skipped and counted in a free row instead of being sold as a current market.
- **Brackets as numbers.** "56-57°F", "9°C", "8°C or below" and "74°F or higher" become `rangeLow` / `rangeHigh` (both included) plus `strikeType` / `floorStrike` / `capStrike` in the same convention as Kalshi, and `temperatureUnit` says F or C. A bracket that cannot be read is returned as a free row with its text, never guessed.
- **Honest empty results.** An unknown city, a stale market, a refusal, a rate limit and a cut-off page each come back as a separate free row that says what happened. Polymarket answers an unknown tag with an empty list (HTTP 200), so before saying "no markets" the Actor checks that the tag still exists.

### Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `cities` | list | (prefilled: NYC, London) | City names as Polymarket writes them. Case, accents and the part in brackets do not matter (`Seoul` and `Incheon` both match "Seoul (Incheon)"; `New York` matches NYC). Empty = every city. |
| `temperatureTypes` | list | both | `high` (daily highest temperature) and/or `low` (daily lowest temperature). |
| `marketStatus` | select | open | `open`, or `closed` (finished, with `result`), newest first. |
| `closedWithinDays` | integer | 7 (closed only) | With `closed`: only events that ended in the last N days (1 to 90; at most 7 in monitoring mode). |
| `liveOrderBook` | boolean | true | Read `yesBid` / `yesAsk` of open markets from the order book. No extra charge. |
| `maxResults` | integer | 1000 | Stop after this many bracket rows (monitoring off). A free row says what was left out. |
| `monitoringMode` | boolean | false | Return only brackets whose displayed Yes price, last trade price, volume, status or result changed since the last run, plus newly listed brackets. |
| `resetMonitoringState` | boolean | false | Forget what monitoring remembered, so the next monitoring run returns everything again. Turn it off after one run. |

Examples:

```json
{ "cities": ["NYC", "London"] }
```

```json
{ "cities": ["Chicago", "Miami"], "temperatureTypes": ["high"] }
```

```json
{ "cities": ["NYC"], "marketStatus": "closed", "closedWithinDays": 30 }
```

### Cities

On 2026-09-21 Polymarket had daily temperature markets for these 51 cities (US cities in °F with 2-degree brackets, the rest in °C with 1-degree brackets, 11 brackets per event): Amsterdam, Ankara, Atlanta, Austin, Beijing, Buenos Aires, Busan, Cape Town, Chengdu, Chicago, Chongqing, Dallas, Denver, Guangzhou, Helsinki, Hong Kong, Houston, Istanbul, Jeddah, Jinan, Karachi, Kuala Lumpur, London, Los Angeles, Lucknow, Madrid, Manila, Mexico City, Miami, Milan, Moscow, Munich, NYC, Panama City, Paris, Qingdao, San Francisco, Sao Paulo, Seattle, Seoul (Incheon), Shanghai, Shenzhen, Singapore, Taipei, Tel Aviv, Tokyo, Toronto, Warsaw, Wellington, Wuhan, Zhengzhou. Polymarket adds and drops cities; an unknown city's free row lists the cities of that moment.

### Same city, different station: Polymarket vs Kalshi

If you compare these markets with Kalshi's (our sister Actor [Kalshi Weather Markets API](https://apify.com/neverempty/kalshi-weather-markets-api) returns the same `targetDate`, `strikeType`, `floorStrike` and `capStrike` columns), check the station first. Stations as named in each market's rules on 2026-09-21:

| City | Polymarket station (`settlementStationCode`) | Kalshi station |
|---|---|---|
| NYC | KLGA LaGuardia Airport | KNYC Central Park |
| Chicago | KORD O'Hare | KMDW Midway |
| Dallas | KDAL Love Field | KDFW Dallas/Fort Worth |
| Denver | KBKF Buckley Space Force Base | KDEN Denver International |
| Houston | KHOU Hobby | KHOU Hobby |
| Miami | KMIA | KMIA |
| Los Angeles | KLAX | KLAX |
| Austin | KAUS | KAUS |
| Seattle | KSEA | KSEA |
| San Francisco | KSFO | KSFO |
| Atlanta | KATL | KATL |

A bracket such as "72-73°F" means the same range on both, but when the stations differ the two markets settle on different thermometers.

### Output

One row per temperature bracket. Example (NYC, highest temperature on 2026-09-22, read 2026-09-21):

```json
{
  "city": "NYC",
  "marketKind": "high",
  "targetDate": "2026-09-22",
  "temperatureUnit": "F",
  "eventTicker": "highest-temperature-in-nyc-on-september-22-2026",
  "marketTicker": "highest-temperature-in-nyc-on-september-22-2026-64-65f",
  "yesLabel": "64-65°F",
  "strikeType": "between",
  "floorStrike": 64,
  "capStrike": 65,
  "rangeLow": 64,
  "rangeHigh": 65,
  "marketStatus": "open",
  "yesPrice": 0.42,
  "yesBid": 0.41,
  "yesAsk": 0.43,
  "yesMid": 0.42,
  "spread": 0.02,
  "pricesFrom": "clob-order-book",
  "lastPrice": 0.48,
  "volumeUsd": 985.03,
  "volume24hUsd": 985.03,
  "liquidityUsd": 6599.88,
  "endDate": "2026-09-22T12:00:00Z",
  "result": null,
  "settlementStationCode": "KLGA",
  "settlementStationName": "LaGuardia Airport",
  "resolutionSource": "https://www.weather.gov/wrh/timeseries?site=klga",
  "scrapedAt": "2026-09-21T07:26:31.180Z"
}
```

| Column | Meaning |
|---|---|
| `city`, `marketKind`, `targetDate` | The city as Polymarket names it, `high` or `low`, and the date the temperature is measured. |
| `inputCity` | The city name you typed that matched this row (`null` when no city was given). |
| `yesLabel`, `rangeLow`, `rangeHigh`, `temperatureUnit` | The bracket as Polymarket shows it and its bounds in whole degrees, both included. `rangeLow` is `null` for "or below" brackets and `rangeHigh` for "or higher" brackets. Polymarket resolves to whole degrees. |
| `strikeType`, `floorStrike`, `capStrike` | The same bracket in Kalshi's convention: `between` = from `floorStrike` to `capStrike`, both included; `less` = below `capStrike` ("8°C or below" has `capStrike` 9); `greater` = above `floorStrike` ("74°F or higher" has `floorStrike` 73). |
| `yesPrice`, `noPrice` | The price Polymarket displays for Yes and No (USD per share; a share pays $1.00). |
| `yesBid`, `yesAsk` | Best price someone is bidding for Yes and best price someone is asking. `null` means no order on that side: Polymarket reports an empty side as 0 (no bid) or 1 (no ask), and neither is returned as a price. Always `null` for closed markets, whose last order book no longer means anything. |
| `yesMid`, `spread` | From `yesBid` and `yesAsk`, only when both exist and the market is open; otherwise `null`. |
| `pricesFrom` | `clob-order-book` (read from the order book during this run) or `gamma-market-data` (Polymarket's market data, which can lag; used when `liveOrderBook` is off or when the order book could not be read). `null` for closed markets. |
| `lastPrice`, `priceChange1h`, `priceChange24h` | Last trade price and Polymarket's 1-hour and 24-hour price change. |
| `volumeUsd`, `volume24hUsd`, `liquidityUsd` | In USD. `null` means Polymarket sent no value; on 2026-09-21 this was the case for 1,088 of 3,124 brackets, and 1,087 of those had no trade yet. |
| `endDate` | Polymarket's end date for the market (noon UTC on the target date). Trading and resolution can continue after it; the rules say the market resolves after the day's data is published. |
| `result`, `resolutionStatus` | For closed markets: `yes` or `no` (from the final 1/0 prices) and Polymarket's resolution status. |
| `settlementStationCode`, `settlementStationName`, `resolutionSource` | The station named in the market rules (ICAO code when the rules link to one) and the link the rules use for resolution. Hong Kong resolves on the Hong Kong Observatory, which has no ICAO code. |
| `eventId`, `eventTicker`, `seriesTicker`, `marketId`, `marketTicker`, `conditionId`, `yesTokenId` | Polymarket identifiers (slugs, condition id and the Yes token id used by the order book). |
| `monitorStatus`, `changedFields` | Monitoring mode only: `first-check` (first time the bracket is returned, including brackets left out of an earlier run by the maximum total charge), `changed` (with the columns that changed) or `new-market` (listed after an earlier run). |

Rows whose `status` is not `ok` are free and explain themselves in `note`: `unknown-city`, `stale-markets-skipped`, `unreadable-strike`, `live-prices-unavailable`, `no-markets`, `duplicate`, `blocked`, `unreadable`, `refused`, `incomplete`, `not-checked`, `budget-reached`, `no-change-since-last-run`, `invalid-input`.

### Pricing

- **$4.00 per 1,000 market rows** (one row per temperature bracket).
- Monitoring mode adds **$0.30 per 1,000 event checks**: each event read (one city, one date, highest or lowest) costs one check, whether or not anything changed. Stale events and failed requests are not charged.
- Live order-book prices cost nothing extra. Free rows (the ones that explain why something was not returned) cost nothing.
- The run stops before it would go over the maximum total charge you set, and a free row says what was left out.

### Monitoring mode

Turn on `monitoringMode` and run the Actor on a schedule (for example every 10 minutes). The first run returns every bracket once as a baseline. Later runs return only brackets whose displayed Yes price, last trade price, volume, status or result changed, plus brackets listed since, with `changedFields` naming what moved. The comparison uses Polymarket's market data only, so a moment when the order book cannot be read never counts as a change. A run with no change returns one free `no-change-since-last-run` row. Markets are remembered per event in a named key-value store; brackets you did not receive because the maximum total charge was reached are not remembered, so the next run returns them if they still differ. Events that ended more than 10 days ago are forgotten. Do not put the same city in two schedules that can run at the same time (Apify's key-value store has no atomic update).

### Notes and limits

- Polymarket returns at most 100 events per page (about 5 MB), so reading every city takes 3 pages; the Actor waits 0.2 s between requests, and a rate limit (HTTP 429) is waited out and retried, then reported as a free `blocked` row if it persists.
- `open` covers events Polymarket lists as open with an end date no more than 3 days past. `closed` reads events that ended within `closedWithinDays`, newest first.
- This Actor returns market data. It does not place orders and is not trading advice. Polymarket may restrict trading in some countries; reading its public data does not change that.

# Actor input Schema

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

Cities to read, one per line, as Polymarket names them, for example NYC, London, Chicago, Tokyo or Seoul. Case, accents and the part in brackets do not matter (Seoul and Incheon both match 'Seoul (Incheon)'; New York matches NYC). Leave the list empty to read every city (51 cities on 2026-09-21). A city with no daily temperature market comes back as a free 'unknown-city' row that lists the cities Polymarket has right now. A repeated city is read and charged once.

## `temperatureTypes` (type: `array`):

high = 'Highest temperature in <city> on <date>' markets, low = 'Lowest temperature in <city> on <date>' markets. Empty = both.

## `marketStatus` (type: `string`):

open = markets Polymarket lists as open (usually today, tomorrow and the day after; events whose end date is more than 3 days past are left out, because Polymarket leaves some old ones marked open without prices). closed = finished markets with the result (the bracket that resolved Yes), newest first, limited by closedWithinDays.

## `closedWithinDays` (type: `integer`):

Used with marketStatus closed: only events whose end date is within the last N days. Empty = 7. At most 7 in monitoring mode. Ignored for open.

## `liveOrderBook` (type: `boolean`):

On = yesBid and yesAsk of open markets come from Polymarket's order book (clob.polymarket.com), read in batches of 200 markets at the time of the run (pricesFrom = clob-order-book). Off, or if the order book cannot be read, they come from Polymarket's market data (pricesFrom = gamma-market-data), which can lag the order book: on 2026-09-21, 4 of 22 NYC brackets differed, one by 9 cents. No extra charge.

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

With monitoring off, the run stops once this many market rows (one row per temperature bracket) have been returned, and a free row says what was not returned. Free rows do not count. In monitoring mode it does not limit the changed markets returned.

## `monitoringMode` (type: `boolean`):

Off = every bracket comes back, charged per row. On = the Actor remembers, per event (one city, one date, highest or lowest), each bracket's displayed Yes price, last trade price, volume, status and result, and later runs return only brackets where one of these changed, plus newly listed brackets. The first run returns every bracket once as a baseline. In monitoring mode every event read costs $0.30 per 1,000 checks, changes or not (events skipped as stale and failed requests are free), plus the row price for the brackets returned. A city usually has 2 or 3 dates open at once, so 2 cities with high and low are about 12 events per run. Example: 12 events every 10 minutes = 51,840 checks a month = $15.55, plus the brackets that changed. The Actor reads only as many events as the run's maximum total charge can pay for with a check and one row each. Do not put the same city in two schedules that can run at the same time.

## `resetMonitoringState` (type: `boolean`):

Clears every remembered market for this Actor, so the next monitoring run returns every bracket again as a first check. This affects all your monitoring runs, because markets are remembered per event rather than per list. Turn it off again after one run: left on in a schedule, every run returns every bracket again and charges for it.

## Actor input object example

```json
{
  "cities": [
    "NYC",
    "London"
  ],
  "marketStatus": "open",
  "liveOrderBook": true,
  "maxResults": 1000,
  "monitoringMode": false,
  "resetMonitoringState": false
}
```

# Actor output Schema

## `results` (type: `string`):

One row per Polymarket daily temperature bracket: city, highest or lowest, target date, unit, bracket bounds, Yes price, yes bid and ask (live order book), last trade, volume, liquidity, end date, result, and the weather station named in the market rules; in monitoring mode only brackets whose price, volume, status or result changed. Unknown cities, stale markets, refusals and limits come back as free rows that say why.

# 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",
        "London"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/polymarket-weather-markets").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",
        "London",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("neverempty/polymarket-weather-markets").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",
    "London"
  ]
}' |
apify call neverempty/polymarket-weather-markets --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/polymarket-weather-markets"
        }
    }
}
```

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/mknrJDuPcsstDhysQ/builds/dM3wmEak7AvA2FnsM/openapi.json
