# Prediction Markets API — Kalshi & Polymarket Odds (`lergassy/prediction-markets-api`) Actor

Kalshi and Polymarket in one table: implied probability, yes and no price, best bid and ask, 24h move, volume, liquidity and close date for every market. Election odds, sports and economic event contracts, with price history and order book. No API key.

- **URL**: https://apify.com/lergassy/prediction-markets-api.md
- **Developed by:** [Matvey](https://apify.com/lergassy) (community)
- **Categories:** Developer tools, Automation, News
- **Features:** Limited permissions
- **Stats:** 62 total users, 31 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $1.05 / 1,000 result rows

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

**Prediction Markets API** puts Kalshi and Polymarket into one table. Every market comes back with the implied probability in per cent, the yes and no price, best bid and ask, the 24-hour move, volume, liquidity, the close date and a link — the same field names for both venues, so you can sort, filter and chart the whole prediction market at once instead of writing two clients.

![One run of Prediction Markets API: Kalshi and Polymarket side by side with probability, volume and liquidity.](https://raw.githubusercontent.com/lergassy/apify-actor-assets/main/prediction-markets-api/prediction-markets-api-output-table.png)

Five modes: **markets** (one row per tradable contract), **events** (one row per question with every outcome and its probability), **search** by keyword, **price history**, and the **order book**. Both APIs are public: no key, no proxy, no browser. A run over both venues takes a few seconds.

### What is Prediction Markets API?

It is a data feed for people who watch what the crowd actually prices: traders, journalists, researchers, dashboard builders and AI agents that get asked "what are the odds the Fed cuts in September". Kalshi is the CFTC-regulated US exchange; Polymarket is the global crypto-settled venue. Their questions overlap on the big themes — rates, elections, wars, crypto, sport — and their prices do not always agree.

### What data does it return?

#### Markets

| Field | Example |
|---|---|
| `platform`, `marketId`, `slug` | kalshi · KXOAIANTH-40-OAI · same ticker |
| `question`, `shortTitle`, `eventTitle` | Will OpenAI or Anthropic IPO first? — OpenAI |
| `probability`, `yesPrice`, `noPrice` | 6.0 (per cent) · 0.06 · 0.94 |
| `bestBid`, `bestAsk`, `spread`, `lastPrice` | 0.05 · 0.07 · 0.02 · 0.06 |
| `priceChange24h` | -0.03 — the move in price, so ±0.03 is three points of probability |
| `volume`, `volume24h`, `volume1w`, `liquidity`, `openInterest` | 171,344 · 4,120 · … |
| `status`, `result` | open · empty until it settles |
| `openTime`, `closeTime`, `endDate` | ISO 8601 |
| `category`, `tags` | Economics · \["Fed Rates", "Politics"] |
| `outcomes` | \[{name: "Yes", price: 0.06, probability: 6.0}, {name: "No", …}] |
| `rules`, `url` | resolution text · link to the market |

Polymarket rows also carry `image` and `clobTokenIds`; Kalshi rows carry `seriesTicker`, `marketType` and `strikeType`.

#### Events

One row per question with `outcomes` sorted most likely first, `favourite` and `favouriteProbability`, `outcomeCount`, total `volume` and `liquidity`, and a ready `summary` sentence. This is the shape for "who will win" questions: one row for *Brazil Presidential Election* with all five candidates and their probabilities, instead of five separate contracts.

#### Compare across venues

`"mode": "compare"` returns one row per question that trades on **both** venues: `kalshiProbability`
and `polymarketProbability`, the `gap` between them in percentage points, `cheaperYes` naming the
venue where a YES contract costs less, both market ids, both links, both volumes and a `summary`
sentence. Rows are ordered by how close the match is and then by combined volume.

Questions are paired on their own wording. The identifying words of the shorter question (names,
places, numbers, thresholds) must appear in the longer one at a rate of at least `compareMinScore`
— 0.55 by default — and three further rules keep the pairs honest: the two contracts must be about
the same **outcome**, not merely the same event, so "2028 Democratic nominee — Michelle Obama" does
not pair with "Will Barack Obama win the 2028 Democratic nomination?"; a market about a party
**nomination** never pairs with one about winning the election; and the two must close within three
weeks of each other, so the 2026 and the 2028 version of the same race stay apart.

Expect a handful of pairs, not a full page: the two venues mostly list different questions, and on a
400-market board across both venues a run typically matches a few. Raise `maxMarkets` to compare a
bigger board, or lower `compareMinScore` to accept looser wording — and read both questions before
acting on a gap.

The pairing is text matching, not a settlement-rules comparison: two markets worded alike can still
resolve differently, so read both `kalshiQuestion` and `polymarketQuestion` before treating a gap as
an arbitrage. Compare needs both venues in `platforms`; if one board comes back empty, or nothing
matches at the current score, the run says so in a free error row instead of returning an empty table.

#### Price history and order book

History returns one row per point with `time`, `price` and `probability` — a week at hourly resolution by default, up to 90 days. The order book returns both sides with price and size per level.

### How much does it cost?

Pay per row, and only for rows you actually get. Every row type costs the same, so a run costs
simply rows × price:

| Row | Price |
| --- | --- |
| Any result row — a market, an event, a comparison, a price point or an order-book snapshot | $0.0015 |

Larger monthly Apify plans pay 10–30 % less per row.

**Error rows are never charged.** There is no browser and no proxy — two public JSON APIs —
so platform usage on top of that is negligible.

| Job | Cost |
| --- | --- |
| 500 markets across both venues | $0.75 |
| One Kalshi market with 7 days of hourly price history (≈168 points) | $0.25 |
| A daily 200-market snapshot for a month | $9.00 |

History is billed per point, so keep `historyDays` short and `marketIds` specific when you only
need the latest move.

Comparable prediction-market Actors charge $0.001 to $0.012 per row and usually cover one
venue; this one returns Kalshi and Polymarket in the same schema.

#### Bulk export: what 50,000 markets actually cost

This Actor is built for bulk jobs — put hundreds of inputs into one run, or call it from the API on
a schedule. There is **no fee per run, no fee per page and no proxy charge**: you pay for the rows
you keep, and error rows are free. That is what decides the bill once you pull a whole market
rather than a single market.

| Job | This Actor | Most-used Actor in this category |
|---|---|---|
| 50,000 markets across 100 runs | **$75** | $600 |

Checked on the Apify Store on 24 September 2026 against the Actor with the most monthly users in
this category; its per-run fee is counted in, as ours would be if we charged one. Some Actors here
ask less per row — this table compares against the one buyers actually use most.

### How to use it

1. Leave **🏛️ Platforms** on both, or pick one.
2. Choose **📋 What to get**: markets, events, search, history or order book.
3. Narrow with **🔍 Keyword** (`fed`, `election`, `bitcoin`), **🏷️ Category** — several at once, `Politics, Crypto` — and a depth filter: **💧 Minimum volume** for how much has traded, **💧 Minimum liquidity** for how much is resting in the book (Polymarket publishes this, Kalshi does not), or **📈 Minimum open interest** for how many contracts are still open (Kalshi's own measure). Both venues list thousands of near-empty contracts, and a volume floor of 1000 keeps the ones people actually trade.
4. Sort by 24-hour volume, total volume, liquidity, closing date, probability or biggest 24-hour move.
5. Click **Start**, then export as JSON, CSV or Excel, or read the dataset through the API.

### ⬇️ Input

![Prediction Markets API input form: the fields a buyer fills in before pressing Start](https://raw.githubusercontent.com/lergassy/apify-actor-assets/main/prediction-markets-api/prediction-markets-api-input-form.png)

```json
{
  "platforms": ["kalshi", "polymarket"],
  "mode": "markets",
  "query": "fed",
  "minVolume": 1000,
  "sortBy": "volume24h",
  "maxMarkets": 200
}
```

#### Events with all outcomes

```json
{ "mode": "events", "category": "Politics", "minVolume": 5000, "maxMarkets": 50 }
```

#### The same question on both venues

```json
{ "mode": "compare", "category": "Politics", "minVolume": 10000, "maxMarkets": 25 }
```

#### Price history for specific markets

```json
{ "mode": "history", "marketIds": ["KXOAIANTH-40-OAI"], "historyDays": 30 }
```

Leave `marketIds` empty and the Actor takes the most active markets instead.

### ⬆️ Output

```json
{
  "type": "market",
  "platform": "kalshi",
  "marketId": "KXOAIANTH-40-OAI",
  "question": "Will OpenAI or Anthropic IPO first? — OpenAI",
  "eventTitle": "Will OpenAI or Anthropic IPO first?",
  "category": "Companies",
  "probability": 6,
  "yesPrice": 0.06,
  "noPrice": 0.94,
  "bestBid": 0.05,
  "bestAsk": 0.07,
  "spread": 0.02,
  "lastPrice": 0.06,
  "priceChange24h": -0.01,
  "volume": 171344.62,
  "volume24h": 2840,
  "liquidity": 18220.5,
  "openInterest": 40639.56,
  "status": "open",
  "closeTime": "2027-12-31T15:00:00Z",
  "outcomes": [
    { "name": "Yes", "price": 0.06, "probability": 6 },
    { "name": "No", "price": 0.94, "probability": 94 }
  ],
  "url": "https://kalshi.com/markets/kxoaianth",
  "scrapedAt": "2026-09-04T01:00:00.000Z"
}
```

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

### Use cases

#### Watching a theme across both venues

Filter on `fed` or `election` and get every contract on both exchanges in one table, with the probability each one implies.

#### Dashboards and newsletters

Sort by 24-hour move to see what repriced overnight, or by closing date for what resolves this week.

#### Research

Pull price history for a set of markets and study how the crowd's estimate moved against the news.

#### Bots and alerts

Schedule the run and alert when a probability crosses a threshold you care about.

#### AI agents

An agent asked "what do prediction markets say about a September rate cut" runs the search mode and reads `probability` straight off the rows.

### 🤖 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/prediction-markets-api`).

**Purpose:** returns what prediction markets currently price for a question, from Kalshi and Polymarket in one shape. Use it for "what are the odds of X", "which markets moved most today", "what does the crowd think about the election".

**Minimal input:**

```json
{ "query": "fed", "minVolume": 1000, "maxMarkets": 50 }
```

**Output:** one row per market — `platform`, `marketId`, `question`, `eventTitle`, `category`, `tags`, `probability` (per cent, the number to quote), `yesPrice`, `noPrice`, `bestBid`, `bestAsk`, `spread`, `lastPrice`, `priceChange24h`, `volume`, `volume24h`, `liquidity`, `openInterest`, `status`, `openTime`, `closeTime`, `outcomes`, `rules`, `url`, `scrapedAt`. Event mode returns `outcomes` sorted by probability with `favourite` and a `summary` sentence; history mode one row per price point; order-book mode one row per market with both sides.

**Behaviors an agent should know:**

- **`probability` is the field to quote**, in per cent. `yesPrice` is the same number as a price between 0 and 1, because one contract pays $1 if the event happens.
- `priceChange24h` is a change in *price*, so 0.03 means three percentage points of probability.
- Both venues list thousands of near-empty markets. Always pass `minVolume` (1000 is a good floor) or the answer fills with noise.
- Filters are applied by this Actor, not by the venues: `query` matches the question, event title and tags; `category` matches Kalshi categories and Polymarket tags.
- A run across both venues interleaves them so neither fills the page; the two report volume on different scales, so compare probabilities, not volumes.
- The venues word the same question differently, so do not assume a Kalshi market and a Polymarket market with similar wording are the same contract. Read both and say which venue each number came from.
- History needs `marketIds`; without them the Actor uses the most active markets. Polymarket history needs the market's CLOB token, which comes from the markets mode.
- Neither API needs a key and no proxy is used.

### Election odds and event contracts in one table

Kalshi and Polymarket price the same kinds of questions and format them differently. This Actor normalises
both into one row shape — implied probability, yes and no price, best bid and ask, 24-hour move, volume,
liquidity and close date — so election odds, economic releases and sports contracts can be compared side by
side without writing two parsers.

### Kalshi API and Polymarket API without keys

Both venues publish open endpoints, and both change shape often. The Actor handles pagination, the differing
price conventions and the end-of-list quirks, and returns the same fields whichever venue a market came from.

### ❓ FAQ

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

No. It reads public market data and returns it as a table. It places no orders and holds no positions. What you do with the numbers is your business, and prediction markets are restricted or illegal in some jurisdictions.

#### Why do Kalshi and Polymarket disagree on the same event?

Different user bases, fees, settlement rules and wording. The gap is real information, but the questions are rarely identical — check the resolution rules in the `rules` field before treating two markets as the same bet.

#### Is the probability the true chance of the event?

It is what the market pays, which is the crowd's price after fees and risk appetite. Treat it as a market price, not a forecast from a model.

#### How fresh are the numbers?

Live at the moment of the run: both APIs serve current order-book state. Schedule the Actor for a time series of your own.

#### Do I need an account on either venue?

No. Both APIs used here are public and read-only.

#### 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 field, or a venue you want added? Open an issue on the **Issues** tab — every one gets answered.

### You might also like

| Actor | What it does |
|---|---|
| Sports Scores & Schedules API | Live scores, schedules and betting lines for 33 leagues |
| [Google Flights Scraper](https://apify.com/lergassy/google-flights-scraper) | Live flight prices, layovers and booking options |
| [US New Business Leads](https://apify.com/lergassy/us-business-filings) | Newly registered US businesses with checked contacts |
| [Email Verifier & Phone Number Validator](https://apify.com/lergassy/email-phone-verifier) | Checks e-mails and phone numbers in bulk |

### Also known as

People look for this Actor as a prediction markets API, a Kalshi API, a Polymarket API, an event contracts feed, prediction market odds, election odds, implied probability data, and betting market data.

### Use via API

Run this Actor from your own code or pipeline. Get your token in Apify Console → Settings → API & Integrations. Every input field below has the same name as in the JSON tab of the input form.

**Python**

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("lergassy/prediction-markets-api").call(run_input={
    "platforms": [
        "kalshi",
        "polymarket"
    ],
    "mode": "markets",
    "sortBy": "volume24h",
    "minVolume": 10000,
    "maxMarkets": 200
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

**JavaScript**

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });
const run = await client.actor('lergassy/prediction-markets-api').call({
    "platforms": [
        "kalshi",
        "polymarket"
    ],
    "mode": "markets",
    "sortBy": "volume24h",
    "minVolume": 10000,
    "maxMarkets": 200
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

**cURL** (runs the Actor and returns the results in one call)

```bash
curl -X POST "https://api.apify.com/v2/acts/lergassy~prediction-markets-api/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"platforms": ["kalshi", "polymarket"], "mode": "markets", "sortBy": "volume24h", "minVolume": 10000, "maxMarkets": 200}'
```

# Changelog

This Actor's version history is a separate document: https://apify.com/lergassy/prediction-markets-api/changelog.md

# Actor input Schema

## `platforms` (type: `array`):

Which venues to read. Keep both to get one table across the whole prediction market.

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

<b>Markets</b> gives one row per tradable contract. <b>Events</b> collapses them into one row per question with every outcome and its probability, which is the shape you want for “who will win” questions. <b>Compare</b> pairs the same question on Kalshi and Polymarket by its wording and close date, and returns one row with both probabilities and the gap between them.

## `query` (type: `string`):

Filter to markets whose question, event or tags contain this text: <code>fed</code>, <code>election</code>, <code>bitcoin</code>, <code>super bowl</code>.

## `category` (type: `string`):

Kalshi category or Polymarket tag: Politics, Economics, Crypto, Sports, Culture, Science. Several at once, comma separated — <code>Politics, Crypto</code> keeps a market matching either.

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

How to order the result.

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

Cap on rows per run. The default is deliberately small so a first run costs cents; raise it once you know which markets you need.

## `marketIds` (type: `array`):

For the history and order-book modes: Kalshi tickers such as <code>KXOAIANTH-40-OAI</code> or Polymarket numeric ids. Leave empty to use the most active markets.

## `seriesTicker` (type: `string`):

Narrow Kalshi to one series, for example <code>KXPRESPARTY</code>.

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

How far back the price history goes. The bucket size follows the window, because the venues cap one by the other: up to 2 days comes back hourly, up to 15 days every 3 hours, up to 30 days every 12 hours, and anything longer in daily points. Every point is a billed row, so a long window across many markets is thousands of rows.

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

Drop thin markets. Both venues list thousands of near-empty contracts; 1000 keeps the ones people actually trade.

## `minLiquidity` (type: `integer`):

Drop markets with less than this much money resting in the book, in US dollars. Polymarket publishes this figure; Kalshi reports zero on almost every market, so on Kalshi use <b>Minimum open interest</b> instead.

## `minOpenInterest` (type: `integer`):

Drop markets with fewer than this many contracts still open. This is Kalshi's measure of how much is actually at stake in a market.

## `includeClosed` (type: `boolean`):

Off by default: only markets you can still trade.

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

Price levels per side in the order-book mode.

## `compareMinScore` (type: `number`):

Only used by compare mode. Two questions are paired when this share of the shorter one's identifying words appears in the other, and the two contracts are about the same outcome and close within three weeks of each other. Lower it to catch looser matches; raise it for near-identical wording only.

## Actor input object example

```json
{
  "platforms": [
    "kalshi",
    "polymarket"
  ],
  "mode": "markets",
  "query": "",
  "sortBy": "volume24h",
  "maxMarkets": 25,
  "historyDays": 7,
  "minVolume": 0,
  "minLiquidity": 0,
  "minOpenInterest": 0,
  "includeClosed": false,
  "orderbookDepth": 10,
  "compareMinScore": 0.55
}
```

# Actor output Schema

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

One row per market with the venue, the question, implied probability in per cent, yes and no prices, best bid and ask, 24h price move, volume, liquidity, close date and link. Compare mode returns one row per matched question with both probabilities and the gap; history mode one row per price point; order-book mode one row per market with both sides.

## `runSummary` (type: `string`):

JSON counters for the run: rows delivered, filtered out, errors and request statistics.

# 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 = {
    "query": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("lergassy/prediction-markets-api").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 = { "query": "" }

# Run the Actor and wait for it to finish
run = client.actor("lergassy/prediction-markets-api").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 '{
  "query": ""
}' |
apify call lergassy/prediction-markets-api --silent --output-dataset

```

## MCP server setup

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

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/nfjcmv74wEU2Qtyhq/builds/dZzqsYZbFyCVajefG/openapi.json
