← Back to blog

Kalshi Doesn't Keep Its Order-Book History. We Recorded It — Depth and Trade Tape Together

By the ZenHodl team — we run the trading bots this blog writes about, and the qualifying live-position record, including losses, is public with its admission rules at /results.

If you've tried to study microstructure on Kalshi, you know the wall: the public API serves trades and candles, not book history. There is no official way to ask "what did the ladder look like at 19:42:31 last Tuesday?" — once a snapshot passes, it's gone. (For a map of the vendors that do record this data — ours and others — see our buyer's guide to historical Polymarket & Kalshi order-book data.)

We've been recording it. Today we're releasing the Kalshi Microstructure Tape: L2 depth and the executed trade tape, together — because depth without prints is a photograph, and prints without depth are footsteps without a floor plan.

What's in it

The honest limits, up front

This is a live capture, and live captures have edges. The trade tape holds every print family the recorder captured — 15 families (game moneylines, spread/total and five European soccer families) in the 2026-09-06 vintage — but it is not a full-exchange tape. MLB print capture went live on 2026-07-10 at 23:04 UTC; the recorder's startup backfill reaches prints created from July 8, so the July 8–10 trade files hold backfilled rather than live-captured MLB prints, and before that the tape is WNBA plus sparse NFL/NCAAF pregame prints. The corrected CAPTURE_STATS.json derives its family list from the delivered parquet. The per-print game-state field is capture-time, not event-time: measured across all 2,039,483 packaged prints of the launch vintage, the poller's retrieval lag was median 26.3s, p90 87s, p99 53 minutes, with 82,183 prints arriving more than five minutes late (mostly quiet-hour and restart backfills); later vintages have not re-measured it — compute it per print from capture_ts − created_time. Every row carries the exchange's created_time, which is what event-time analysis should join on. The depth ladder is capped at 20 levels per side (Kalshi exposes more; we store the top 20). Our capture host slept through two windows in mid-July, and has been intermittently dark since August 9. The corrected coverage map derives gaps over 120 seconds from adjacent global poll timestamps in UTC; 150 qualifying gaps occur August 14–September 6. A global poll says some selected book was captured, not that every ticker was present or continuously observed.

We list all of this because one overclaim costs more trust than ten disclosures. It's also why we keep capturing and cut refreshed dated vintages: every day of capture is a day nobody else can go back and get.

Start with $9

The tryout contains Jul 18–19 UTC write-day partitions — ~21.5M depth rows and 747K prints across both feeds, using the same data schema but its own manifest and coverage note. A boundary depth poll is timestamped Jul 17 23:59:42 UTC. Neither partition has a global-poll gap over two minutes, but that does not guarantee every ticker was sampled at every poll. Build your pipeline against it; if the data isn't what you need, you found out for $9. A free 400-row sample and the complete schema are on the samples page.

To verify a personalized ZIP, hash its included MANIFEST.json bytes and compare that digest with this SKU's archive_metadata.source_documents entry in the public catalog. Only after it matches, check the sizes and hashes of the files named in that manifest. A buyer ZIP's whole-file hash changes when its license comment is added.

Research and backtest data, not signals — as with everything we sell.

Related reading

Get ZenHodl Weekly

One weekly email with live results, one model insight, and product updates.

Tuesday mornings. No spam.

Research Kalshi market microstructure

Measured snapshot cadence, 20-level depth, executed prints, game-state timing, and disclosed capture gaps.