# Prediction Markets Feed — Polymarket, Kalshi, Manifold (`dirtycode/prediction-markets-feed`) Actor

Unified, normalized live odds across prediction markets — Polymarket, Kalshi and Manifold in one schema, one call. Implied probability, spread, volume, open interest and market lifecycle. Public data: no login, no API key, no account.

- **URL**: https://apify.com/dirtycode/prediction-markets-feed.md
- **Developed by:** [Dirtycode](https://apify.com/dirtycode) (community)
- **Categories:** Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$5.00 / 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.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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

## Prediction Markets Feed — Polymarket · Kalshi · Manifold

One **unified, normalized** live odds feed across prediction-market venues. Every venue's
quirks flattened into a single schema, so you compare prices instead of parsing three APIs.
All public data — **no login, no API key, no account.**

### Output (per market)

| Field | Description |
|---|---|
| `platform` | polymarket · kalshi · manifold |
| `question`, `ticker`, `url` | Market identity + link |
| `subtitle` | What a YES resolves to, when a question is split across outcomes |
| `yesPrice`, `noPrice` | Implied probability (0..1) |
| `spread` | Vig / implied edge |
| `volume`, `liquidity`, `openInterest` | Market depth |
| `volumeUnit`, `liquidityUnit` | **What those numbers count** — see below |
| `closeTime`, `status`, `resolvedOutcome` | Lifecycle |

**Depth fields vary by venue, and we report what each one actually gives us.** Kalshi publishes
no liquidity figure — it returned 0.0000 on all 803 markets sampled, including one with 167k
volume — so `liquidity` is `null` there rather than a zero that would claim a deep market has
none. Manifold has no open interest. A `null` here means "this venue does not publish it", never
"it is zero".

⚠️ **`volume` is NOT the same unit on every venue — do not sum or rank across them on it.** This
is the one place a unified schema can quietly mislead you, so every row now carries `volumeUnit`:

| venue | `volumeUnit` | what one unit is |
|---|---|---|
| polymarket | `usd` | dollars that actually changed hands (price × shares) |
| kalshi | `contracts` | contracts traded — $1 of **max payout** each, not $1 traded |
| manifold | `play-money` | mana. Not redeemable for anything. |

The gap between Kalshi's number and Polymarket's is the price. KXELONMARS-99 reports 114,563.30
contracts at $0.12, so about **$13.7k** changed hands against **$114.6k** of notional: reading it
as USD overstates it 8.3× there, and by 1/price in general. Ranking *within* one venue is sound.

We deliberately do not convert them to a common unit — lifetime volume × today's price is not
what traded, so the "unified" number would be invented rather than measured.

### Input

```json
{ "platforms": ["polymarket", "kalshi", "manifold"], "limit": 100 }
```

- **platforms** — which venues to include.
- **limit** — markets per venue, which also bounds what the run costs.

### Pricing

Pay per event: **$0.005 per market returned** (`market-returned`). You only pay for rows you
actually receive; a run that returns nothing fails and charges nothing.

### Use cases

Quant research, odds aggregation, probability tracking across venues, AI agents that need live
market data.

### What this actor does not do

**Cross-venue arbitrage detection was removed rather than shipped.** It matched markets by
question text, and across 300 live markets from three venues that found zero pairs — venues never
phrase the same question identically. Loosening the match does not fix it: the closest pairs were
"Will Eric Trump win the 2028 election" against "Will Trump announce he is running", and the next
Prime Minister of **Ethiopia** against the next Prime Minister of **Romania**. Any threshold loose
enough to match anything matches those, and an arbitrage signal that confuses two countries costs
you money.

Doing it properly needs semantic equivalence — same underlying event, same resolution criteria,
same date — which is a different product, not a setting. If you want it, say so and it gets built
properly.

***

#### For the developer (not shown on the Store)

Thin wrapper over the private `scraper-gateway`. Set Actor **environment variables** (secret):
`SCRGW_URL`, `SCRGW_SECRET`. Pay-per-event: `market-returned` ($0.005). The gateway's
`/v1/predictions/arbitrage` route still exists for internal use — it is simply not sold.
Deploy: `apify push --force`.

# Actor input Schema

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

Which prediction-market venues to include. Repeated venues are ignored: each venue is fetched and charged once.

## `limit` (type: `integer`):

Max markets fetched per venue. Also bounds what the run costs.

## `proxy` (type: `string`):

Optional proxy for the requests. Leave empty to use the default.

## Actor input object example

```json
{
  "platforms": [
    "polymarket",
    "kalshi",
    "manifold"
  ],
  "limit": 100
}
```

# 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 = {
    "platforms": [
        "polymarket",
        "kalshi",
        "manifold"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("dirtycode/prediction-markets-feed").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 = { "platforms": [
        "polymarket",
        "kalshi",
        "manifold",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("dirtycode/prediction-markets-feed").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "platforms": [
    "polymarket",
    "kalshi",
    "manifold"
  ]
}' |
apify call dirtycode/prediction-markets-feed --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=dirtycode/prediction-markets-feed",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/cSQCooEm3aRJvt6lx/builds/WdTIL1fA7BzSsxdyc/openapi.json
