Polymarket & Kalshi Arbitrage Monitor
Pricing
Pay per event
Polymarket & Kalshi Arbitrage Monitor
Match public Polymarket and Kalshi binary contracts, compare outcome prices, and export confidence evidence with candidate cross-market spread calculations.
Pricing
Pay per event
Rating
0.0
(0)
Developer
Stas Persiianenko
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
5 days ago
Last modified
Categories
Share
Compare open binary contracts across Polymarket and Kalshi, inspect current outcome prices, and export explainable candidate spread calculations.
This prediction market app monitor reads the two venues' public APIs, identifies likely equivalent propositions, evaluates both YES/NO venue combinations, and saves ranked records to an Apify dataset.
It is designed for recurring prediction market arbitrage research, pricing dashboards, and analyst review—not automated trading.
What does this Actor do?
The Actor:
- loads open public binary contracts from Kalshi;
- loads open public binary contracts from Polymarket;
- blocks pairs with conflicting parties, offices, directions, or numeric terms;
- scores remaining pairs using shared terms, numeric terms, and expiry proximity;
- compares
Kalshi YES + Polymarket NOwith the reverse combination; - subtracts your configurable fee and slippage estimate;
- ranks and exports matched contracts with source links and matching evidence.
Every result contains both source quotes. You can inspect why a pair matched instead of relying on an opaque label.
Who is this prediction market app monitor for?
- Prediction-market analysts comparing prices across platforms.
- Quant researchers building an observation history from scheduled runs.
- Traders creating a shortlist for manual settlement-rule and depth checks.
- Journalists and academics studying cross-platform pricing differences.
- Data teams feeding matched prediction market prices into a warehouse or dashboard.
- Automation builders feeding analytical output into their own external alert workflows.
Why use it?
Polymarket and Kalshi describe related contracts differently. A direct title join misses useful pairs, while a loose keyword join creates dangerous false matches.
This Actor combines:
- public structured APIs rather than browser automation;
- event and contract context from both venues;
- conservative proposition-conflict checks;
- an explainable confidence score;
- displayed bid/ask, liquidity, volume, expiry, and source identity;
- configurable topic, confidence, expiry, liquidity, fee, and spread filters;
- stable match IDs for recurring monitoring.
It does not claim that a high score proves identical settlement rules. Manual verification remains essential.
What data can I export?
| Field | Meaning |
|---|---|
rank | Position after candidate status, net spread, and confidence sorting |
matchId | Stable hash of the Kalshi and Polymarket market IDs |
matchedTitle | Human-readable Kalshi event and proposition |
strategy | Lower-cost displayed YES plus NO venue combination |
candidateArbitrage | Whether estimated net spread meets your threshold |
combinedCost | Displayed ask cost for a theoretical $1 payout |
grossSpreadPercent | (1 - combinedCost) × 100 |
estimatedFeesPercent | User-provided fee and slippage estimate |
estimatedNetSpreadPercent | Gross spread minus estimated fees |
matchConfidence | Similarity score from 0 to 1 |
matchReasons | Shared terms, numeric evidence, and expiry evidence |
expiryDifferenceHours | Difference between displayed expiry timestamps |
kalshi | Kalshi identity, URL, expiry, prices, liquidity, and volume |
polymarket | Polymarket identity, URL, expiry, prices, liquidity, and volume |
observedAt | UTC observation timestamp |
Price, liquidity, or volume fields can be null when a source does not provide them.
How to run the monitor
- Open the Actor in Apify Console.
- Leave
keywordsempty for broad discovery, or add a real topic such asAlexandria Ocasio-Cortez. - Choose how many contracts to scan per venue.
- Keep
minMatchConfidenceat0.4initially. - Set a realistic combined fee and slippage estimate.
- Keep
includeNonProfitableenabled when you need all matched price comparisons. - Disable it when you only need pairs meeting
minNetSpreadPercent. - Click Start.
- Review the Matched prediction contracts dataset view.
- Open both source URLs and compare full settlement rules before acting.
Input parameters
keywords
Optional topic phrases. A phrase must appear in both contracts in a pair. Use it to focus a run on a state, candidate, asset, league, or macro topic.
maxItems
Maximum matched records saved to the default dataset. Allowed range: 1–1,000. Default: 25.
maxMarketsPerVenue
Maximum open binary contracts loaded from each venue. Allowed range: 100–5,000. Default: 1,500.
Higher coverage takes longer but may find more current overlap.
minMatchConfidence
Minimum lexical, numeric, and expiry confidence. Allowed range: 0.2–1. Default: 0.4.
Lower values increase recall and false-match risk. Raise the value for precision-sensitive workflows.
maxExpiryDifferenceHours
Reject pairs whose displayed expiries differ by more than this value. Default: 720 hours.
Different timestamps can still represent similar settlement periods, so always inspect the rules.
estimatedFeesPercent
Combined fee and slippage estimate subtracted from the gross spread. Default: 2%.
This is an analytical assumption, not a source-provided quote.
minNetSpreadPercent
Threshold used for candidateArbitrage and, when filtering is enabled, dataset inclusion.
Default: 0%.
minLiquidityUsd
Require both source contracts to report at least this displayed liquidity. Default: 0.
A zero value preserves contracts where liquidity is omitted.
includeNonProfitable
When true, matched contracts remain useful for cross-market monitoring even if the estimated spread is below the threshold.
When false, only threshold-meeting pairs are saved.
Example input
{"keywords": ["Alexandria Ocasio-Cortez"],"maxItems": 10,"maxMarketsPerVenue": 5000,"minMatchConfidence": 0.4,"maxExpiryDifferenceHours": 720,"estimatedFeesPercent": 2,"minNetSpreadPercent": 0,"includeNonProfitable": true}
This current-data example returns matched 2028 nomination propositions while they remain open on both venues. Prediction-market inventories change, so a topic can naturally return no records later.
Example output
{"rank": 1,"matchId": "a761264d80a3dd2169e7","matchedTitle": "2028 Democratic presidential nominee: Will Alexandria Ocasio-Cortez be the Democratic Presidential nominee in 2028?","strategy": "Buy Kalshi YES + Polymarket NO","candidateArbitrage": true,"combinedCost": 0.98,"grossSpreadPercent": 2,"estimatedFeesPercent": 2,"estimatedNetSpreadPercent": 0,"matchConfidence": 0.893,"matchReasons": ["7 shared terms: 2028, democratic, presidential, nominee, alexandria, ocasio, cortez","6 shared adjacent phrases","matching numeric terms: 2028","contract expiries differ by 15 hours"],"expiryDifferenceHours": 15,"kalshi": {"venue": "Kalshi","marketId": "KXPRESNOMD-28-AOC","url": "https://kalshi.com/markets?search=KXPRESNOMD-28-AOC","yesAsk": 0.18,"noAsk": 0.83},"polymarket": {"venue": "Polymarket","marketId": "559653","url": "https://polymarket.com/event/democratic-presidential-nominee-2028","yesAsk": 0.201,"noAsk": 0.8},"observedAt": "2026-08-15T07:01:59.971Z"}
Quotes move continuously. The example shows the record shape, not a current recommendation.
How matching confidence works
The matcher first creates candidate pairs sharing at least one indexed term. It then scores:
- overlap relative to the shorter title;
- Jaccard overlap across both titles;
- matching numeric proposition terms;
- displayed expiry proximity.
It rejects pairs with conflicting:
- political parties;
- political offices;
- above/below or before/after directions;
- increase/decrease directions;
- numeric proposition terms.
matchReasons exposes the supporting evidence.
Even a score of 0.99 is not a settlement guarantee.
How candidate spread calculations work
For each pair, the Actor compares:
Kalshi YES ask + Polymarket NO askPolymarket YES ask + Kalshi NO ask
It selects the cheaper displayed combination.
gross spread % = (1 - combined cost) × 100estimated net spread % = gross spread % - estimatedFeesPercent
The calculation does not model order-book depth, partial fills, deposits, withdrawals, taxes, changing quotes, or venue-specific settlement risk.
How much does it cost to monitor Polymarket and Kalshi spreads?
The Actor uses pay-per-event pricing:
- one
startevent per run; - one
itemevent for each matched record actually saved; - no charge for rejected, duplicate, or failed candidate pairs.
The active rates are a $0.01 start plus the applicable tiered item rate. At the BRONZE item rate of $0.0016 per match, example totals are:
| Saved matches | Example total |
|---|---|
| 1 | $0.0116 |
| 10 | $0.026 |
| 100 | $0.17 |
Apify account tiers can apply different item rates. Always check the pricing panel for the active tier before a run. Compute usage is covered by the Actor under PPE pricing.
Scheduling recurring arbitrage monitoring
Create an Apify Schedule with a stable input.
For monitoring, keep includeNonProfitable enabled so a spread history does not disappear when it crosses zero.
A useful workflow is:
- run every 15–60 minutes;
- export dataset rows to a table keyed by
matchIdandobservedAt; - compare the latest two observations;
- alert only after your own confidence, liquidity, rule-equivalence, and fee checks;
- retain source URLs for auditability.
The Actor itself does not place orders or send trading alerts.
Export to spreadsheets, databases, and BI tools
The default dataset works with:
- CSV and Excel exports;
- Google Sheets integrations;
- webhooks and Make;
- Zapier;
- REST API clients;
- Python notebooks;
- JavaScript data pipelines;
- BigQuery, Snowflake, or PostgreSQL loaders;
- dashboard tools such as Looker Studio and Power BI.
Use matchId as a cross-run pair key.
Use observedAt as the observation time.
Do not use rank as a stable identifier.
Run through the Apify API with cURL
curl -X POST \"https://api.apify.com/v2/acts/automation-lab~polymarket-kalshi-arbitrage-monitor/runs?token=$APIFY_TOKEN&waitForFinish=300" \-H "Content-Type: application/json" \-d '{"keywords": ["Alexandria Ocasio-Cortez"],"maxItems": 10,"maxMarketsPerVenue": 5000,"minMatchConfidence": 0.4,"includeNonProfitable": true}'
Fetch dataset items from the defaultDatasetId returned by the run.
Do not put tokens in committed source code.
Run with JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('automation-lab/polymarket-kalshi-arbitrage-monitor').call({keywords: ['Alexandria Ocasio-Cortez'],maxItems: 10,maxMarketsPerVenue: 5000,minMatchConfidence: 0.4,includeNonProfitable: true,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);
Run with Python
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ["APIFY_TOKEN"])run = client.actor("automation-lab/polymarket-kalshi-arbitrage-monitor").call(run_input={"keywords": ["Alexandria Ocasio-Cortez"],"maxItems": 10,"maxMarketsPerVenue": 5000,"minMatchConfidence": 0.4,"includeNonProfitable": True,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item)
Use with Apify MCP
Add the Actor to Claude Code:
claude mcp add --transport http apify \"https://mcp.apify.com?tools=automation-lab/polymarket-kalshi-arbitrage-monitor"
Claude Desktop setup
Add this server to Claude Desktop's MCP configuration:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com?tools=automation-lab/polymarket-kalshi-arbitrage-monitor"}}}
Cursor setup
Add the same apify HTTP server URL under Cursor Settings → MCP and enable it for the workspace.
VS Code setup
Add the same apify HTTP server URL to the VS Code MCP server configuration, then start the server from the MCP tools panel.
Example prompts:
- “Run the Polymarket Kalshi monitor for Alexandria Ocasio-Cortez and summarize matched prices.”
- “Scan both platforms, keep non-profitable matches, and return the five highest-confidence pairs.”
- “Run with zero estimated fees and show positive displayed gross spreads for manual review.”
Treat model summaries as secondary analysis; preserve the source dataset and URLs.
Limits and failure behavior
- The public source APIs can change, rate-limit, or temporarily fail.
- The Actor retries transient failures and uses a second public Kalshi API host.
- Deterministic source errors fail the run rather than returning fabricated or stale records.
- Coverage is bounded to 5,000 open contracts per venue to keep runtime and pair evaluation predictable.
- A successful run can contain zero records when no contracts meet all filters.
- Keywords apply to both sides of a pair.
- Non-binary and Kalshi multivariate contracts are excluded.
- Prices are snapshots and can change before any order is placed.
- Displayed liquidity does not guarantee executable depth at the shown price.
- Similar wording does not guarantee identical resolution criteria.
Responsible use and legality
The Actor accesses public, unauthenticated market-data endpoints. Use the output in accordance with Apify's terms, each source's terms, and laws applicable to you.
Prediction-market access and trading rules differ by location. This Actor does not bypass login, geofencing, or access controls. It does not provide financial, legal, tax, or investment advice. It does not execute trades.
Before relying on a pair:
- open both source links;
- compare the complete settlement wording and authoritative sources;
- confirm contract side orientation;
- inspect live order-book depth;
- account for every fee and transfer cost;
- confirm your eligibility to use each venue;
- make your own independent decision.
Troubleshooting
Why did the run return no matches?
Current overlap may be naturally sparse.
Remove keywords, increase maxMarketsPerVenue, keep includeNonProfitable enabled, or cautiously lower minMatchConfidence.
Do not lower confidence merely to force a result.
Why was an apparent opportunity omitted?
The pair may have conflicting numbers, direction words, political parties, offices, expiry distance, liquidity, or confidence. It may also sit beyond the bounded open-contract window.
Why is an obvious false match present?
No automated semantic matcher is perfect.
Raise minMatchConfidence, add a topic keyword, and report the two source URLs and IDs for reproducible improvement.
Never trade solely from the Actor's candidate label.
Why is candidateArbitrage false?
The pair is still a useful cross-market comparison, but its estimated net spread is below minNetSpreadPercent after subtracting estimatedFeesPercent.
Set includeNonProfitable to false to omit those rows.
Does this guarantee risk-free profit?
No. Settlement wording, timing, fills, depth, fees, eligibility, transfers, and price movement create material risk. The Actor outputs candidates for verification, not guarantees.
Related automation-lab Actors
- Polymarket Markets Scraper exports individual Polymarket markets without cross-venue matching.
- Kalshi Markets Scraper exports detailed Kalshi markets and filters without cross-venue matching.
Use the source-specific Actors when you need broader raw inventory or venue fields. Use this Actor when the buyer job is matched cross-market monitoring and spread calculation.
FAQ
Are prices live?
They are public API snapshots observed during the run, not streaming quotes. Schedule repeated runs for a time series.
Can I search only one venue?
No. This product emits cross-venue matches. Use the related source-specific Actor for single-venue exports.
Can I add multiple keywords?
Yes. A contract is accepted when any configured phrase appears, but each pair must pass the same keyword scope on both venues.
Does the Actor need a proxy or account?
No. It uses public anonymous APIs and exposes no automatic paid-proxy fallback.
Does it place trades?
No. It only exports analytical records.
How should I deduplicate scheduled results?
Use matchId for the pair and observedAt for each snapshot.
Can I use the data in an agent workflow?
Yes. Use Apify MCP or the REST API, but require the agent to show both source URLs, confidence reasons, and settlement-rule caveats.
Support
For reproducible help, include:
- the Actor run URL;
- exact input;
- the two source market IDs or URLs;
- expected versus observed behavior;
- whether the source pages and APIs were available at run time.
Do not include API tokens, credentials, or private trading information.