# Prediction Markets Scraper: Kalshi, Polymarket & Manifold (`camalot/prediction-markets`) Actor

Live odds, prices, volume and price history from Kalshi, Polymarket and Manifold in one clean, unified schema. Search by keyword, filter by status, compare venues. Uses official public APIs only.

- **URL**: https://apify.com/camalot/prediction-markets.md
- **Developed by:** [Cameron Fagan](https://apify.com/camalot) (community)
- **Categories:** AI, Developer tools, News
- **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 Scraper: Kalshi, Polymarket & Manifold

Get live odds, prices, volume, liquidity and price history from **Kalshi**, **Polymarket** and **Manifold Markets**, all returned in **one unified schema**. Search by keyword ("bitcoin", "fed", "election"), compare the same question across venues, or pull every open market ranked by volume.

Uses only the venues' **official public APIs**. No login, no cookies, no proxies, no browser, so runs are fast, cheap and reliable.

### What you can do with it

- **Compare odds across venues.** See what Kalshi, Polymarket and Manifold each price for the same event, and spot arbitrage or mispricing.
- **Feed trading bots and AI agents** with clean, consistent JSON instead of three different APIs.
- **Track sentiment over time** with daily or hourly price history.
- **Research resolved markets.** Pull closed markets with their final resolution for backtesting and calibration studies.
- **Build dashboards and alerts** on elections, crypto, the Fed, sports, AI, weather and more.

### Input

| Field | Description |
|---|---|
| `sources` | Any of `kalshi`, `polymarket`, `manifold`. |
| `search` | Optional keyword. Whole-word match on the market question, so `fed` finds "Fed rate cut" but not "Federico". |
| `status` | `open` (trading now) or `closed` (resolved). |
| `maxItemsPerSource` | Max markets per venue, highest volume first. |
| `minVolumeUsd` | Skip thin markets. |
| `includePriceHistory` | Attach a YES-price time series (Kalshi, Polymarket). |
| `historyDays`, `historyInterval` | Lookback and resolution (`hour` / `day`). |

Example:

```json
{
  "sources": ["kalshi", "polymarket", "manifold"],
  "search": "bitcoin",
  "status": "open",
  "maxItemsPerSource": 50,
  "includePriceHistory": true,
  "historyDays": 30
}
```

### Output

One row per tradable YES contract (example below; values illustrative). Multi-outcome events (e.g. "Bitcoin price at end of 2026" with price buckets, or "Who wins the House?") become one row per outcome, so every row has a single YES price.

```json
{
  "source": "polymarket",
  "marketId": "0x…",
  "eventId": "what-price-will-bitcoin-hit-in-2026",
  "question": "Will Bitcoin reach $250,000 by December 31, 2026?",
  "outcome": "↑ 250,000",
  "url": "https://polymarket.com/event/…",
  "status": "open",
  "yesPrice": 0.0065,
  "noPrice": 0.9935,
  "yesBid": 0.006,
  "yesAsk": 0.007,
  "lastTradePrice": 0.0065,
  "outcomes": [{ "name": "Yes", "price": 0.0065 }, { "name": "No", "price": 0.9935 }],
  "volume": 5493137,
  "volume24h": 41210,
  "volumeUnit": "usd",
  "volumeUsd": 5493137,
  "volume24hUsd": 41210,
  "liquidityUsd": 120334,
  "openInterest": null,
  "createdTime": "2025-12-31T…",
  "closeTime": "2026-12-31T…",
  "resolution": null,
  "rules": "This market will resolve to \"Yes\" if…",
  "priceHistory": [{ "t": "2026-09-27T00:00:00.000Z", "price": 0.007 }],
  "scrapedAt": "2026-10-04T…"
}
```

Prices are probabilities from 0 to 1 (0.25 = 25% = 25¢).

#### Notes per venue

- **Kalshi**: `volume` is in contracts. Each contract settles at $1, so contracts ≈ USD notional, and `volumeUsd` uses that. `openInterest` is included.
- **Polymarket**: volumes and liquidity in USD (USDC). Bid/ask from the order book.
- **Manifold**: play-money markets. `volume` is in **mana**, not dollars, so `volumeUsd` is empty. Multiple-choice markets are split into one row per answer.

### Pricing

Pay per result: you're charged per market returned, plus a small extra per market when price history is attached. No monthly fee. Set a maximum charge per run in Apify and the scraper stops cleanly when it's reached.

### Use with AI agents

Works with the Apify MCP server and API, so agents (Claude, ChatGPT, LangChain, n8n, Make, Zapier) can call it directly, e.g. *"get current odds on all Fed markets across Kalshi and Polymarket"*.

### FAQ

**Is this allowed?** It reads public market data from each venue's official public API, the same data shown on their websites. It doesn't log in, place trades, or touch any private data.

**How fresh is the data?** Live at the moment the run executes. Schedule the Actor (e.g. every 15 minutes) for a continuous feed.

**A venue was down. Does the run fail?** No. Each venue is fetched independently; if one fails, the others still return results and the error is logged.

**Found a bug or want another venue?** Open an issue on the Issues tab. Requests are welcome.

# Actor input Schema

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

Which prediction markets to pull from.

## `search` (type: `string`):

Only return markets whose question/title contains this word or phrase (whole-word, case-insensitive), e.g. "bitcoin", "election", "fed rate". Leave empty for all markets.

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

Open = currently trading. Closed = trading ended / resolved.

## `maxItemsPerSource` (type: `integer`):

Upper limit of markets returned from each venue. Markets are sorted by volume (highest first) where the venue supports it.

## `minVolumeUsd` (type: `integer`):

Skip thin markets. Total traded volume in USD (Manifold: in mana, its play-money currency).

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

Attach a YES-price time series to each market (Kalshi and Polymarket). Charged as an extra event per market.

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

How many days of price history to fetch when price history is enabled.

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

Time between price points.

## Actor input object example

```json
{
  "sources": [
    "kalshi",
    "polymarket",
    "manifold"
  ],
  "search": "bitcoin",
  "status": "open",
  "maxItemsPerSource": 50,
  "minVolumeUsd": 0,
  "includePriceHistory": false,
  "historyDays": 30,
  "historyInterval": "day"
}
```

# Actor output Schema

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

One row per tradable YES contract: odds, bid/ask, volume, liquidity, close time, resolution and optional price history.

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

Markets returned per venue, plus the search and status used.

# 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 = {
    "sources": [
        "kalshi",
        "polymarket",
        "manifold"
    ],
    "search": "bitcoin",
    "maxItemsPerSource": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("camalot/prediction-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 = {
    "sources": [
        "kalshi",
        "polymarket",
        "manifold",
    ],
    "search": "bitcoin",
    "maxItemsPerSource": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("camalot/prediction-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 '{
  "sources": [
    "kalshi",
    "polymarket",
    "manifold"
  ],
  "search": "bitcoin",
  "maxItemsPerSource": 50
}' |
apify call camalot/prediction-markets --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,camalot/prediction-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/2NldnPPDfGcceFk3Z/builds/LO8oLXfhWFa2LpHV7/openapi.json
