Polymarket vs Kalshi Arbitrage — Same Question, Two Prices avatar

Polymarket vs Kalshi Arbitrage — Same Question, Two Prices

Pricing

from $20.00 / 1,000 contract pair priced across venues

Go to Apify Store
Polymarket vs Kalshi Arbitrage — Same Question, Two Prices

Polymarket vs Kalshi Arbitrage — Same Question, Two Prices

Give it a question that trades on both Polymarket and Kalshi and get the price gap between them, after Kalshi's fee. Returns best bid and ask on each site, which site to buy on and sell on, the gap in cents per $1 contract. $0.02 per pair priced, suggestions included; refusals are free. Unofficial.

Pricing

from $20.00 / 1,000 contract pair priced across venues

Rating

0.0

(0)

Developer

h ichi

h ichi

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

6 days ago

Last modified

Share

What it does: Takes a question that trades on both Polymarket and Kalshi and prices the gap between them, before and after the Kalshi fee (Polymarket charges none today).

You enter: Pairs you checked, e.g. will-bitcoin-outperform-gold-in-2026|KXBTCVSGOLD-26 (Polymarket|Kalshi).

You get: One row per pair: best bid and ask on each site, which site to buy on and sell on, gap in cents per $1 before and after the fee, dollars resting at those prices, close-date gap. Pairs it suggests itself (on by default) are marked unverified, indicative only.

Price: $0.02 per pair priced, the pairs it suggests included. +$0.002 per site row if you also want each side (two per pair, on by default). Pairs that can't be priced are never charged.

Unofficial — not affiliated with Polymarket or Kalshi. Reads public pages only.

Confirmed pairs — the only tradable number

You list the pairs you have checked, as "<polymarket-slug-or-conditionId>|<KALSHI-TICKER>". Only these get an edgePct.

fieldmeaning
matchVerifiedtrue — you confirmed this pairing
directione.g. "buy polymarket / sell kalshi" — which leg you lift
edgePct(bid on the dearer venue - ask on the cheaper) x 100, cents per $1 contract
edgeNetPctthe same, less the Kalshi fee on the executed leg
kalshiFeeCents / polymarketFeeCentsper contract; see Fees below
polymarketDepthUsd / kalshiDepthUsddollars resting at the touch, bid and ask
closeGapDayshow far apart the two contracts settle
directionsBlockedthe round trip that was not taken, and why

Suggested pairs — never a trade, always a question

With autoSuggest on, the matcher proposes pairings it found. These carry matchVerified: false, edgePct: null, and their number under the deliberately different name indicativeEdgePct — alongside matchScore, matchBasis (what actually matched), closeGapDays, and both resolution texts verbatim (polymarketResolution, kalshiResolution) so you can confirm or reject in one glance. confirmAs gives you the exact string to paste into pairs.

Reading them matters. In a live run on 2026-08-10 the matcher proposed OpenAI IPO before 2027? against Kalshi's Who will IPO before 2027? OpenAI — same company, same year, an 8-point apparent edge. The two resolution texts do not agree: Polymarket needs the IPO completed by 31 Dec 2026, Kalshi needs it confirmed before 1 Jan 2027. Announcing is easier than completing, so Kalshi trades higher for a reason. That gap is a definition, not an arbitrage — and it is visible only because both texts travel with the suggestion.

What the matcher refuses to do

Every gate below is a hard drop, not a score penalty, because a fact that is simply wrong cannot be traded off against wording similarity. Each one's losses are counted in the summary.

gatewhy
close times more than maxCloseGapDays apartcontracts that settle weeks apart are not the same contract
token overlap below minMatchScore
numeric thresholds present on both sides but disagreeing"BTC above $150,000" and "BTC above $120,000" are 0.75 similar as text and are opposite bets
dates present on both sides but disagreeing
opposite direction words (above / below)the one pairing that would flip the sign of the edge
a qualifier on one side only (second, exactly, not, consecutive)"second-hottest year" vs "hottest year" is one word and the opposite bet
the shared words are more common than the differing onessee below

That last gate came out of a live run. At minMatchScore 0.6 the matcher paired "Remote IPO before 2027?" with "Who will IPO before 2027? Kraken" — two different companies whose entire overlap is the template ipo / before / 2027. A candidate is now dropped unless the rarest word the two questions share is at least as rare as the rarest word they differ on.

What it counts

A filtered set that hides its own losses reads as complete, so the spread_summary record reports every drop: droppedCloseGap, droppedPolarity, droppedAsymmetricQualifier, droppedNumericThresholdDisagreement, droppedDateDisagreement, droppedNoSharedSubjectWord, droppedBelowMatchScore, duplicateKalshiSuggestionsDropped, duplicatePolymarketSuggestionsDropped, unpriceableLegs, confirmedPairsUnresolvable. Verified and unverified edge statistics are kept in separate fields and never averaged together.

Depth, and what is refused

minLiquidityUsd applies to the size resting at the touch on both legs — the Polymarket side from the CLOB order book, the Kalshi side from yes_bid_size / yes_ask_size, each valued at its own price. Gamma's book-wide liquidity is reported separately as bookWideLiquidityUsd and is not used for this, because it is not the size behind the quote.

A pair is refused, not priced, when:

  • either venue has no two-sided quote (one side of the book is empty);
  • the depth a direction needs is below minLiquidityUsd, in both directions;
  • a leg is not accepting orders, or is not a binary Yes/No market;
  • the pair string does not resolve to one market on each venue.

Every refusal names the input to change and is returned with the record rather than dropped.

Fees

  • Kalshi: ceil(coefficient x P x (1 - P)) dollars per contract, rounded up to the next cent — 2c on a 50c contract. The coefficient (published: 0.07) is an input, because a stale fee constant would quietly overstate every edge.
  • Polymarket: no trading fee is charged today; every live market measured on 2026-08-10 carries feesEnabled: false. This is stated rather than silently assumed.
  • Gas / relayer cost on the Polymarket leg is not modelled. A net edge smaller than your own transaction cost is not a trade.

What one row looks like

Measured on 2026-08-09 (real run) — one confirmed pair, a few fields left out for length

{
"type": "confirmed_pair",
"pair": "will-bitcoin-outperform-gold-in-2026|KXBTCVSGOLD-26",
"matchVerified": true,
"polymarketQuestion": "Will Bitcoin outperform Gold in 2026?",
"kalshiQuestion": "Will Bitcoin outperform gold in 2026?",
"polymarketYesBid": 0.17,
"polymarketYesAsk": 0.19,
"kalshiYesBid": 0.178,
"kalshiYesAsk": 0.215,
"polymarketDepthUsd": { "bid": 1.7, "ask": 19.0 },
"kalshiDepthUsd": { "bid": 0.93, "ask": 10.24 },
"closeGapDays": 0.0,
"priced": true,
"edgePct": -1.2,
"edgeNetPct": -3.2,
"direction": "buy polymarket / sell kalshi",
"kalshiFeeCents": 2,
"polymarketFeeCents": 0,
"directionsBlocked": []
}

Each row also carries feeModel and depthBasis in plain words, so the numbers above can be checked without reading this page.

Price

$0.02 per contract pair priced — every pair that gets a price is charged, including the ones the tool suggests itself, so ten priced pairs cost $0.20. A refused pair is never charged: a pair without a two-sided quote on both venues, or with a leg too thin to trade, produced no answer, and you do not pay for a non-answer.

Each venue's side of a pair is $0.002 and on by default (includeIndividualLegs), two per priced pair — confirmed and suggested alike. A refused pair carries no leg rows and no leg charge, because a refusal is free whole. Turn it off if you only want the pair rows. You pay per pair; there is no monthly fee.

Input

{
"pairs": ["will-bitcoin-outperform-gold-in-2026|KXBTCVSGOLD-26"],
"autoSuggest": true,
"categories": ["Financials"],
"maxEventsPerVenue": 1000,
"maxCloseGapDays": 3,
"minMatchScore": "0.6",
"minLiquidityUsd": "0",
"kalshiFeeCoefficient": "0.07"
}

categories filters the Kalshi side only, and it is the lever that matters: Kalshi carries over 8,000 open events, so scanning without a category is scanning a slice of an arbitrary ordering. Pick the categories your pairs live in (Politics, Economics, Elections, Financials, Companies, Crypto, World, Sports, Climate and Weather).

maxEventsPerVenue defaults to 200 and tops out at 1000; the example above asks for the maximum.

Reads both sites' public data only, no login, requests spaced out. Nothing is kept between runs — every run re-reads both live order books.

If something goes wrong

  • Wrong number or a failed run? Open a ticket on the Issues tab. I read every one and reply within 2 business days (Japan time).
  • You never get a fake "empty" result. If the site can't be read, the run fails and says so.
  • A pair that can't be priced = no charge. A pair that does get a price costs $0.02 even when the gap comes out negative — that number is the result you asked for.
  • Checked every week. An automatic test runs this tool weekly; if the site changes, I fix it.
  • Public pages only. No login, no personal data, and it goes easy on the site.

More tools by the same author

All tools (Japan marketplaces, real estate, jobs, racing, prediction markets): https://apify.com/jpmarketdata

Disclaimer

Unofficial, independent tool — not affiliated with, endorsed by, or sponsored by Kalshi or Polymarket. Product names and logos belong to their owners and only say where the data comes from. Data is read from public pages, for market research; check before you act on it.