# Prediction Market Arb Scanner — Polymarket + Kalshi + PredictIt (`congism/polymarket-kalshi-predictit-arb-finder`) Actor

Scans Polymarket, Kalshi, and PredictIt for matching binary prediction markets and surfaces every cross-platform pair where buying YES on one and NO on the other locks in a risk-free profit. Wider net than a single pair — three platforms means three pairwise comparisons per scan.

- **URL**: https://apify.com/congism/polymarket-kalshi-predictit-arb-finder.md
- **Developed by:** [Cong](https://apify.com/congism) (community)
- **Categories:** Automation, Developer tools, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.05 / actor start

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 Market Arb Scanner — Polymarket + Kalshi + PredictIt

Scans [Polymarket](https://polymarket.com), [Kalshi](https://kalshi.com), and [PredictIt](https://www.predictit.org) simultaneously, matches binary prediction markets on the same topic across every platform pair, and surfaces price discrepancies where you can lock in a **risk-free profit** by buying YES on one platform and NO on the other.

This is a wider-net version of the two-platform Polymarket/Kalshi arb finder: with three sources, every scan checks three pairwise combinations (Polymarket x Kalshi, Polymarket x PredictIt, Kalshi x PredictIt) instead of just one, and results from all three are pooled into a single ranked list.

### How the arbitrage works

All three platforms resolve the same way: YES pays $1.00/share, NO pays $0.00/share (or vice versa). If Polymarket prices a market at **YES = $0.43** and PredictIt prices the matching contract at **YES = $0.39**:

| Action | Cost | Payout if YES | Payout if NO |
|--------|------|---------------|--------------|
| Buy YES on PredictIt | $0.39 | +$1.00 | $0.00 |
| Buy NO on Polymarket | $0.57 | $0.00 | +$1.00 |
| **Total** | **$0.96** | **$1.00** | **$1.00** |

**Guaranteed profit: $0.04 per share = ~4% return regardless of outcome.**

### Why PredictIt needs no credentials

Polymarket and PredictIt both expose public, unauthenticated market data APIs — no login required for either. Kalshi requires an account (email + password) to fetch live prices; without Kalshi credentials, the scan still runs Polymarket x PredictIt.

### What you get per opportunity

| Field | Description |
|-------|-------------|
| `platform_pair` | Which two platforms this opportunity spans, e.g. `polymarket x predictit` |
| `spread` | YES price difference between platforms (0-1 scale) |
| `return_pct` | Estimated profit % per dollar risked |
| `direction` | Which platform to buy YES on, which to buy NO on |
| `buy_yes_url` / `buy_no_url` | Direct links to each side of the trade |
| `cost_per_unit` / `profit_per_unit` | Total cost to capture $1 payout, and guaranteed profit |
| `similarity_score` | How closely the two market questions matched (0-1) |
| `<platform>_question`, `<platform>_yes_price`, etc. | Full per-platform detail for both legs of the trade |

### Input options

| Parameter | Default | Description |
|-----------|---------|-------------|
| `minSpread` | `0.02` | Minimum price difference to flag (e.g. 0.05 = 5 cents) |
| `minReturnPct` | `0.5` | Minimum profit % to include |
| `maxReturnPct` | `100` | Sanity cap — excludes implausibly large "returns", which are almost always a false match rather than a real opportunity (see note below) |
| `minSimilarity` | `0.4` | Keyword match strictness (higher = fewer, more accurate matches). Below 0.4, unrelated markets sharing generic keywords (e.g. year numbers) can get matched and produce fake high-return results that sort to the top — see note below |
| `minLiquidity` | `0` | Filter out illiquid markets (PredictIt has no liquidity field, so PredictIt markets are exempt) |
| `minVolume24h` | `0` | Filter by 24h trading volume (PredictIt has no volume field, so PredictIt markets are exempt) |
| `maxResults` | `500` | Cap on results, sorted by return % |
| `includePredictIt` | `true` | Toggle PredictIt on/off |
| `kalshiEmail` / `kalshiPassword` | — | Optional — enables the Kalshi legs of the scan |

### Important notes

- **Not financial advice.** Real arb requires all trades to fill simultaneously. Slippage, fees, and timing can reduce or eliminate the profit.
- **PredictIt is US-only and has contract price caps** ($850 per contract per market as of this writing) — factor that into position sizing.
- **Matching uses IDF-weighted keyword similarity, not plain Jaccard.** An earlier version used the same unweighted keyword-overlap algorithm as the existing Polymarket/Kalshi finder, and testing surfaced a serious failure mode on multi-candidate races: "Will Tim Scott win the 2028 Republican nomination?" and nine other longshot candidates all matched to the *same* PredictIt "Vance" contract, because the shared race boilerplate ("2028", "republican", "presidential", "nomination") outweighed the one word that actually distinguishes candidates — the surname. This version weights each keyword by inverse document frequency across the whole scan, so boilerplate shared by dozens of markets in the same race counts for little, while a candidate's surname (which appears in only one or two markets) dominates the score. Validated against live data: correct same-candidate matches now score 0.6–0.76, while every wrong-candidate match in the same race scores 0.27–0.36 — a clean gap the default 0.4 threshold sits in.
- **Also fixed: plural/singular mismatches on party names.** Polymarket often phrases a question as "Will the Republicans win..." (plural) while PredictIt names the equivalent contract "Republican" (singular) — as plain strings these never overlap, so the one word that should anchor the match was silently missing, and a same-race two-party market could match to the *opposite* party's contract (confirmed live: a Kansas governor market matched to the Democratic contract instead of the near-identically-priced Republican one, producing a fake 100% "arb" that was really the same bet placed twice in the same direction). Keywords are now lightly singularized before matching, which fixed this specific case and reduced the overall result set from double/triple-digit fake returns to a realistic 0.5%–9% range in a full re-scan.
- **This is a real improvement, not a guarantee.** Unusual phrasing, nicknames, or very short/common surnames could still occasionally produce a false match. **Always verify the two markets resolve on the same underlying event and the same side of it before trading** — a `similarity_score` below 0.5 deserves a manual look, and treat every result as a lead, not an executable trade.
- `maxReturnPct` (default 100) additionally excludes any match claiming an implausibly large guaranteed return, which in practice is almost always a sign the matching got it wrong rather than a real opportunity.
- Kalshi is CFTC-regulated and US-accessible; Polymarket is accessible to non-US users only; PredictIt operates under a CFTC no-action letter and is capped at 5,000 traders per market by regulation.
- PredictIt's public API does not expose volume or liquidity data, so those two filters only ever narrow Polymarket/Kalshi results.

### Example output

```json
{
  "platform_pair": "polymarket x predictit",
  "similarity_score": 0.75,
  "spread": 0.0395,
  "return_pct": 4.11,
  "profit_per_unit": 0.0395,
  "cost_per_unit": 0.9605,
  "direction": "Buy YES on predictit, NO on polymarket",
  "buy_yes_on": "predictit",
  "buy_yes_price": 0.39,
  "buy_yes_question": "Who will win the 2028 Republican presidential nomination? - Vance",
  "buy_yes_url": "https://www.predictit.org/markets/detail/...",
  "buy_no_on": "polymarket",
  "buy_no_price": 0.5705,
  "buy_no_question": "Will J.D. Vance win the 2028 Republican presidential nomination?",
  "buy_no_url": "https://polymarket.com/event/...",
  "scanned_at": "2026-07-31T16:40:00.000Z"
}
```

### Related Actors

Also from the same developer:

- **[Polymarket + Kalshi Arbitrage Finder](https://apify.com/congism/polymarket-kalshi-arb-finder)** — the original two-platform version this Actor extends.
- **[Polymarket Markets Scraper](https://apify.com/congism/polymarket-markets-scraper)** — raw Polymarket market data (prices, volume, liquidity, CLOB token IDs) if you just need the feed without cross-platform matching.

# Actor input Schema

## `minSpread` (type: `number`):

Minimum YES price difference between platforms to flag as an arb opportunity (0-1 scale). Example: 0.05 means at least 5 cents difference. Default: 0.02.

## `minReturnPct` (type: `number`):

Minimum estimated profit % per dollar risked. Example: 1.0 = only show opportunities worth at least 1% return. Default: 0.5.

## `maxReturnPct` (type: `number`):

Excludes opportunities claiming an implausibly large guaranteed return, which in practice almost always means the two markets were mismatched (e.g. two different candidates in the same race matched to each other) rather than a real arb. Raise this only if you plan to manually verify every result. Default: 100.

## `minSimilarity` (type: `number`):

Keyword similarity threshold (0-1) for matching markets across platforms. Higher = stricter matching, fewer but more accurate pairs. Values below 0.4 frequently produce false matches between unrelated markets that happen to share generic keywords (e.g. year numbers) — these show up as huge fake spreads and sort to the top, so don't lower this without also raising minReturnPct or manually reviewing every result. Default: 0.4.

## `minLiquidity` (type: `number`):

Only include markets with at least this much liquidity. Filters out thin markets where you can't fill a meaningful position. Note: PredictIt's public API does not expose liquidity, so PredictIt markets are exempt from this filter. Default: 0.

## `minVolume24h` (type: `number`):

Only include markets with at least this much 24-hour trading volume. Note: PredictIt's public API does not expose 24h volume, so PredictIt markets are exempt from this filter. Default: 0.

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

Maximum number of arb opportunities to return, sorted by return % descending. Default: 500.

## `includePredictIt` (type: `boolean`):

PredictIt's market data API is public and needs no credentials. Disable to scan Polymarket/Kalshi only.

## `kalshiEmail` (type: `string`):

Your Kalshi account email. Required to fetch Kalshi market prices. Without this, Kalshi is skipped and only Polymarket/PredictIt pairs are scanned.

## `kalshiPassword` (type: `string`):

Your Kalshi account password. Stored securely and only used to authenticate with the Kalshi API.

## Actor input object example

```json
{
  "minSpread": 0.02,
  "minReturnPct": 0.5,
  "maxReturnPct": 100,
  "minSimilarity": 0.4,
  "minLiquidity": 0,
  "minVolume24h": 0,
  "maxResults": 500,
  "includePredictIt": true,
  "kalshiEmail": ""
}
```

# 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("congism/polymarket-kalshi-predictit-arb-finder").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("congism/polymarket-kalshi-predictit-arb-finder").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 '{}' |
apify call congism/polymarket-kalshi-predictit-arb-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=congism/polymarket-kalshi-predictit-arb-finder",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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