# Prediction Markets Data: Kalshi and Polymarket Odds API (`pistachio_implementation/prediction-markets-data`) Actor

Get Kalshi and Polymarket prediction market odds, prices, volume, order books and price history in one clean schema. Filter by category, keyword, status and minimum volume. Official public APIs, no login.

- **URL**: https://apify.com/pistachio\_implementation/prediction-markets-data.md
- **Developed by:** [Hay Equipos](https://apify.com/pistachio_implementation) (community)
- **Categories:** News, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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

## Prediction Markets Data: Kalshi and Polymarket Odds API

Pull live and historical prediction market data from **Kalshi** and **Polymarket** in one clean, normalized table. Every row is one market with its implied probability, best bid and ask, last price, volume, liquidity, close time and a link. Optionally add an order book snapshot and a price history series for each market.

The actor reads only the exchanges' official public market data APIs. No login, no cookies, no account, no personal data.

### What you can do with it

- Track the odds on elections, Fed decisions, inflation prints, sports, weather and more across both exchanges at once.
- Compare the same question on Kalshi and Polymarket to spot price gaps.
- Feed forecasting models, trading bots, dashboards or AI agents with a steady, consistent schema.
- Pull daily or hourly price history for backtests and charts.
- Snapshot the order book to measure depth and spread.

### How it works

1. Choose the exchanges, the market status (open, closed or settled) and your filters: keyword, categories and minimum volume.
2. The actor scans the exchange listings, applies your filters and keeps the markets with the highest total volume, up to your limit per exchange.
3. If you ask for them, it adds an order book snapshot and a price history for the Yes side of each market.
4. Results land in the dataset. Export them as JSON, CSV, Excel or through the API.

### Input example

```json
{
    "sources": ["kalshi", "polymarket"],
    "keyword": "fed",
    "categories": ["Economics", "Economy"],
    "status": "open",
    "minVolume": 1000,
    "maxMarkets": 25,
    "includeOrderBook": true,
    "orderBookDepth": 5,
    "includePriceHistory": true,
    "historyDays": 7,
    "historyInterval": "1d"
}
```

| Field | What it does |
|---|---|
| `sources` | `kalshi`, `polymarket` or both |
| `keyword` | Keeps markets whose question, event title or outcome contains this text |
| `categories` | Kalshi categories (Politics, Economics, Sports, Climate and Weather, Financials and so on) or Polymarket tags (Politics, Crypto, Sports, Economy and so on). Case insensitive |
| `status` | `open`, `closed` or `settled` (settled applies to Kalshi; on Polymarket it is treated as closed) |
| `minVolume` | Minimum total volume. Kalshi counts contracts, Polymarket counts US dollars |
| `maxMarkets` | Maximum markets per exchange, highest volume first |
| `includeOrderBook`, `orderBookDepth` | Adds the top bids and asks for the Yes side |
| `includePriceHistory`, `historyDays`, `historyInterval` | Adds hourly or daily Yes prices for the last N days |
| `maxPagesPerSource` | Safety cap on listing pages scanned per exchange (default 80) |

### Output example

```json
{
    "source": "kalshi",
    "marketId": "KXLAYOFFSYINFO-26-494000",
    "marketUrl": "https://kalshi.com/markets/kxlayoffsyinfo",
    "eventId": "KXLAYOFFSYINFO-26",
    "eventTitle": "More tech layoffs in 2026 than in 2025?",
    "question": "More tech layoffs in 2026 than in 2025?",
    "outcomeLabel": "Yes",
    "category": "Economics",
    "tags": ["Economics"],
    "status": "open",
    "result": null,
    "openTime": "2026-02-25T15:00:00Z",
    "closeTime": "2027-03-01T15:00:00Z",
    "yesBid": 0.948,
    "yesAsk": 0.954,
    "lastPrice": 0.949,
    "impliedProbability": 0.951,
    "volume": 31479865.08,
    "volume24h": 1360.67,
    "volumeUnit": "contracts",
    "liquidityUsd": 0,
    "openInterest": 166499.19,
    "outcomes": [
        { "name": "Yes", "price": 0.951, "tokenId": null },
        { "name": "No", "price": 0.049, "tokenId": null }
    ],
    "orderBook": {
        "side": "yes",
        "sizeUnit": "contracts",
        "bids": [{ "price": 0.948, "size": 86.25 }],
        "asks": [{ "price": 0.954, "size": 6.7 }],
        "snapshotAt": "2026-09-27T05:35:59.368Z"
    },
    "priceHistory": [
        { "timestamp": "2026-09-26T04:00:00.000Z", "price": 0.955, "yesBid": 0.951, "yesAsk": 0.955, "volume": 102.3 }
    ],
    "scrapedAt": "2026-09-27T05:35:33.086Z"
}
```

Prices are in US dollars per share or contract, from 0 to 1, so a price of 0.62 means the market puts the Yes outcome at about 62%. `impliedProbability` is the midpoint of the best bid and ask when both exist, otherwise the last price (Kalshi) or the listed outcome price (Polymarket).

Polymarket rows carry the real outcome names and CLOB token ids in `outcomes`, which is useful for multi outcome markets.

### Pricing

Pay per event, no subscription and no charge for platform usage:

| Event | Price |
|---|---|
| Market record saved | $0.001 (that is $1 per 1,000 markets) |
| Order book snapshot added | $0.001 per market |
| Price history added | $0.001 per market |

A daily pull of the top 100 markets on both exchanges with order books costs about $0.40. You can cap your spend with the maximum charge setting on each run; the actor stops cleanly when the cap is reached.

### Limits

- Kalshi does not offer server side keyword search, so the actor scans all listing pages for the chosen status (about 65 pages and 120,000 markets for open markets, which takes around 30 seconds). Closed and settled history is very large; raise `maxPagesPerSource` to go deeper.
- Kalshi volume is counted in contracts and Polymarket volume in US dollars. The `volumeUnit` field says which.
- Order book and price history cover the Yes side (the first outcome on Polymarket). The No side is the mirror image on binary markets.
- Kalshi multi leg combo markets (parlays) are not included.
- Data is as published by each exchange at the time of the run. This is market data, not investment advice.
- Not affiliated with Kalshi or Polymarket.

### FAQ

**Do I need a Kalshi or Polymarket account?** No. The actor reads only public market data.

**Can I run it on a schedule?** Yes. Use Apify schedules to run it hourly or daily and send results to Google Sheets, a webhook or your database.

**Why is Polymarket missing from my results?** Polymarket blocks some countries at the network level. Apify's servers are not affected, but if you run the actor on your own machine in a blocked country, the Polymarket part will fail and Kalshi results are still saved. The run log names any exchange that failed.

**How do I match the same question across exchanges?** Filter both with the same keyword and compare `question`, `closeTime` and `impliedProbability`. Each exchange words its markets differently, so automatic matching is not attempted.

**Something broke or you need a field added?** Open an issue on the actor's Issues tab. Issues are answered quickly.

# Actor input Schema

## `sources` (type: `array`):

Which exchanges to pull from.

## `keyword` (type: `string`):

Only keep markets whose question, event title or outcome contains this text (case insensitive). Leave empty for all markets.

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

Only keep markets in these categories, for example Politics, Economics, Sports, Crypto, Climate and Weather. Matched case insensitively against the Kalshi category and the Polymarket event tags. Leave empty for all.

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

Open markets are trading now. Closed means trading has stopped (on Polymarket this includes resolved markets). Settled is Kalshi only.

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

Drop markets with less total traded volume than this. Kalshi volume is counted in contracts (each pays $1), Polymarket volume in US dollars.

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

Stop after this many markets per exchange. Results are sorted by total volume, highest first.

## `includeOrderBook` (type: `boolean`):

Add the current bids and asks for each market (one extra request per market).

## `orderBookDepth` (type: `integer`):

How many price levels to keep on each side of the book.

## `includePriceHistory` (type: `boolean`):

Add the price history of the Yes outcome for each market (one extra request per market).

## `historyDays` (type: `integer`):

How many days of price history to fetch.

## `historyInterval` (type: `string`):

Spacing between price history points.

## `maxPagesPerSource` (type: `integer`):

Safety cap on how many listing pages are scanned per exchange. Raise it for full scans of closed or settled markets.

## Actor input object example

```json
{
  "sources": [
    "kalshi",
    "polymarket"
  ],
  "status": "open",
  "minVolume": 0,
  "maxMarkets": 50,
  "includeOrderBook": false,
  "orderBookDepth": 10,
  "includePriceHistory": false,
  "historyDays": 7,
  "historyInterval": "1d",
  "maxPagesPerSource": 80
}
```

# Actor output Schema

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

All rows the run saved to the default dataset.

## `summary` (type: `string`):

The RUN\_SUMMARY record: counts and problems for the whole run.

# 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("pistachio_implementation/prediction-markets-data").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("pistachio_implementation/prediction-markets-data").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 pistachio_implementation/prediction-markets-data --silent --output-dataset

```

## MCP server setup

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

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/Ht9qSpEMXy1t3G2SE/builds/iKDaM25mz3i9HhMqt/openapi.json
