How TapeXray measures Kalshi vs Polymarket gaps (2026)

TapeXray counts a Kalshi-Polymarket pair as one bet when both mids are between 15¢ and 85¢, the gap is at most 12¢ and under 35 % of the cheaper mid, confidence is at least 0.75, and both sides traded $1,000 in 24 h. Fees are priced twice: at Polymarket's 7 % maximum, then at each market's rate.

Where do TapeXray's numbers come from?

Everything on this site is computed from one archive that TapeXray collects itself: the public market catalogs and order books of Kalshi and Polymarket, read on a schedule and stored as dated partitions. Nothing is typed in from a venue's marketing page. The archive currently holds 263,852 markets, 54,802 of them on Kalshi and 209,050 on Polymarket, and its newest catalog partition is dated 2026-09-26. The market pages show only markets that cleared $100,000 in traded volume, because a page about a market nobody trades would be a page about a quote, not a price.

The live board is built from that same archive by a matcher that pairs Kalshi and Polymarket sub-markets on their title tokens and then reads the latest order book on each side. A pair enters the board with two mids, a raw gap, the matcher's confidence score and both sides' 24-hour volume; the gate described in the next section decides whether it is shown as a real pair, as a pair the fees eat, or disclosed as suspect with the reason. Every figure on this page is read from that export when the site is built, not from the prose around it, which is why the counts here match the board's own on the same deploy.

Which matched pairs count as the same bet?

A title match is not proof. The matcher cannot tell one team's win market from the other's, and two venues' longshots are routinely two different questions, so the board applies a same-bet gate to every matched pair before it prices anything. The gate is version 4; its rules and thresholds are read from the code that applies them, so the table below cannot describe a gate the board is not running. A pair that fails any rule is not deleted: it is exported as suspect with the rule that rejected it, and the board discloses the count.

The same-bet gate, version 4
RuleThresholdWhy it exists
Both mids inside the band15¢ to 85¢Longshot books quote in whole cents, so a small gap on a cheap side looks large; two venues' longshots are routinely two different bets.
Gap relative to the cheaper midat most 35 %A same-outcome gap is a few percent of the price, not a multiple of it.
Raw gap between the two midsat most 12¢Same-outcome prices on two venues rarely differ by more than a few cents.
Title-match confidenceat least 0.75The matcher pairs sub-markets by title tokens and cannot tell one team from the other on its own.
Traded volume, both sides, last 24 hat least $1,000Under that a mid is one resting order wide of nothing; a missing volume fails the floor rather than passing by default.
Source: pmsite.xmatch's gate constants (suspect_reason), read at export time

The funnel below is the last scan's, counted over the full lists rather than the capped tables the board displays. Most of the loss is at the top, in books that were dead or missing and in pairs the gate rejected; the number that survives to "positive after fees" is small on most days, and that is the honest shape of the data, not a failure of the scan.

The last scan's funnel, 2026-09-26 02:33 UTC
StagePairs
Matched pairs from the matcher13,539
Dropped: no order book on one side5,873
Dropped: dead book (a side pinned at the edge)3,152
Dropped: stale book8
Rejected by the same-bet gate (disclosed as suspect)4,498
Passed the gate8
Passed, but round-trip fees eat the gap8
Positive after fees0
Source: xmatch.json's funnel block, gate version 4, counted over the uncapped lists

How are fees modelled, and why in two passes?

Both venues charge takers on expected earnings, rate x P x (1 - P) per contract, where P is the contract price in dollars, so the fee peaks at a price of one half and shrinks toward either end of the range. Kalshi's rate is one number, its general schedule of 0.07, rounded up to the next cent on an order. Polymarket has no single rate: each market publishes its own on its catalog row, by category, from fee-free to a maximum of 0.07. TapeXray measures that distribution instead of typing it, from a sample of 20,000 of the 11,637,244 catalog rows the archive holds; the Polymarket fee page publishes it with row counts.

Pricing every one of the matcher's pairs at its market's real rate would mean a catalog read per pair, which exceeds the export's memory budget. So the board prices in two passes. Pass one gates and ranks every pair at the Polymarket maximum, the conservative direction, which means no pair is ever admitted that its true rate would have excluded. Pass two re-prices only the pairs that passed the gate at each market's own catalog rate, so the fee-adjusted gap can only rise on re-pricing. A market with no readable schedule keeps the maximum and says so in its fees block. The fee calculator runs the same formula on both venues, and the Kalshi fee page works through the rounding.

The two fee passes
PassPolymarket rateKalshi rateApplied to
Pass 1: gate and rank0.07, the published maximum0.07, general scheduleevery matched pair (13,539 on the last scan)
Pass 2: re-priceeach market's own catalog rate (11 measured categories)0.07, general schedulegated pairs only (8 on the last scan)
Source: pmsite.fees' rate constants and pmsite.xmatch.FEE_NOTE / reprice_gated

What does per $100 mean, and why do the board and the fork card use different units?

Two conventions appear on this site and they are deliberately not mixed in one view. The board's gaps are in cents after round-trip fees: the difference between the two venues' mids, minus taker fees on both legs, doubled for entry and exit, because a bettor who crosses a gap between two mids has to get out again. That is the number the board ranks by and the number the "fees eat it" list is measured against, and it can only be compared with other round-trip figures.

A fork is a different trade. Buying YES on one venue and NO on the other for a total under $1 holds to resolution, so there is no exit leg and each side pays one-way taker fees once: Kalshi's rounded up to the whole cent, Polymarket's at the market's own catalog rate. The fork card and the alert bot express that as money on a $100 payout, "put in this, get back $100, keep the difference", scaled from the per-pair figure so that a reader sees a stake they can picture rather than a margin in fractions of a cent. When the depth of the books is not known, the card says so, because the book decides how many pairs it takes to fill $100. Neither convention is converted into the other on a page, and a figure quoted from this site should say which one it is.

How fresh is the number on the page?

The site is a static export of the archive, rebuilt on a schedule every 6 hours. Each rebuild re-reads the catalogs, re-runs the matcher's gate over the latest order books, re-prices the survivors, and writes the numbers on every page from that one export, so a figure is never fresher than the last deploy and never older than it either. The board's own stamp is the time its pairs were scored, 2026-09-26 02:33 UTC; the fee table's stamp is the date its catalog sample was drawn, 2026-09-26; the archive's stamp is the newest catalog partition, 2026-09-26. The three can differ by hours and that difference is real: a book is read more often than a catalog is re-listed.

The gate version travels with every recorded day, and the rolling windows on the board restart whenever it changes, so a figure from one gate regime is never averaged into another. The availability changelog records what changed on the state pages and when; it is not this page, and it does not describe method.

What does this site not verify?

A methodology that lists only what it checks is a brochure. The table below is the standing list of claims this site relies on but has not independently verified, with the reason. Each row exists as a documented fact in the project's own records before it appears here, and the status column reads the export's own flags where one exists, so "not re-verified" turns into "verified" on the deploy after the check succeeds and not before. If a row here is wrong, or a claim on the site is missing from it, the contact page reaches the desk directly.

What this site does not verify
ClaimStatusWhy
Kalshi's 7 % general taker ratedocumented, not re-verifiedkalshi.com's fee-schedule PDF has returned HTTP 429 to every fetch since 2026-09-21; the rate is retained from the previously read schedule.
Kalshi per-series fee multipliersunpriced; every series is charged at a multiplier of 1.0Kalshi's series endpoint carries a fee_multiplier, but the archive has no series table, so a series above 1.0 is priced too generously here.
Polymarket's per-category rate tablemeasured from a sample of 20,000 of 11,637,244 catalog rows (0 %)Reading every row's schedule exceeds the export's memory cap, so a rare category can be under-represented in one day's read.
That a gated pair is the same outcomegated, not provenThe matcher works from title tokens; the gate rejects the implausible pairs and discloses them as suspect, but it cannot read a rulebook.
Kalshi's close_time as a settlement datenot used as oneIt is a trading ceiling that can sit days after the event, so the two venues' settlement timing is disclosed as a risk rather than gated on.
Source: docs/forks.md §11, docs/measurements/2026-09-23-fee-sample-oom.md, fees.json's verified flag and pmsite.xmatch's gate comments

By The TapeXray deskCopy last reviewed

See the live board this page describes →