How to get the Polymarket Price To Beat at T0 — the open price the instant the window opens
Every Polymarket crypto Up/Down market resolves against one number: the Price To Beat (PTB) — the opening reference price. Final price > PTB → Up wins; below it → Down. If you're building anything on "BTC Up or Down", the PTB is the number your whole edge depends on.
And there is no API for it on crypto markets. Worse: by the time the PTB shows up anywhere you can read it, your 5-minute window is already closing. The fix isn't to scrape it harder — it's to resolve it at T0 (the instant the window opens) from the same upstream sources Polymarket itself uses.
"Read it off the page" comes too late
The frontend does render the PTB and outcome — but only ~20 seconds after the window closes. That's perfect for recording results or backfilling history. It's useless for entry, where you need the open price before the window runs. Different problem, different data path.
To act at the open, you have to go to the source.
Where the open price actually comes from (it depends on the cycle)
This is the reverse-engineered part. There is no single feed — each timeframe resolves against a different one:
| Cycle | Reference price (the PTB) |
|---|---|
| 5m / 15m / 4h | the Chainlink oracle stream Polymarket resolves against — first tick at/after the window boundary |
| 1h | the Binance 1-hour candle OPEN at the window start |
| 1d | the Binance 1-minute candle CLOSE at the official noon-ET open |
Use one source for all of them — say, the live Chainlink price for the daily too — and you'll be off, sometimes by hundreds of dollars, and you won't get an error. You'll just get the wrong winning side.
The boundaries aren't all UTC
- 5m / 15m / 1h start on UTC grid lines.
- 4h starts on America/New_York hours (00/04/08/12/16/20). A fixed UTC formula is wrong half the year because EST and EDT differ by an hour.
- 1d starts at noon ET — not UTC midnight, not ET midnight. "Up or Down on March 5" runs Mar 4 noon ET → Mar 5 noon ET, and the PTB is taken at Mar 4 noon ET. A DST-transition day is 23 or 25 hours, so the end is "noon ET + one calendar day", never "start + 86400".
Don't read the daily candle early
The daily uses the close of the 1-minute candle at noon ET. Binance returns that candle the moment it opens, but until it closes, close is just the latest trade — not the final close:
open_time, _, _, _, close, _, close_time, *_ = candle[0]
if now_ms <= int(close_time):
raise NotReady("1m candle hasn't closed; CLOSE is still live")
price_to_beat = float(close)
Also: Binance startTime is a filter, not an exact match — always check the returned candle's open_time equals the t_start you asked for.
One async call at T0
With the per-cycle source mapping and the Eastern-time boundaries handled, getting the open price becomes a single call:
ptb = await resolver.get_ptb(asset, tf, t_start)
# 5m/15m/4h -> first Chainlink tick at/after t_start
# 1h -> Binance 1h candle OPEN
# 1d -> Binance 1m candle CLOSE at noon ET (waited until final)
For 5m/15m/4h the resolver subscribes to the real-time Chainlink feed and takes the first tick at or after the boundary — the open price in real time, long before on-chain settlement.
Two complementary approaches
If all you need is the settled result after the fact, the free page-scraper reads the rendered Outcome (and PTB) ~20s after close:
https://github.com/BlueWhale-Quant-Lab/Polymarket-Crypto-UpDown-Outcome-Scraper
But for entry you need the PTB at the open, in real time, from the underlying sources — which is exactly what the T0 resolver does. I packaged the full per-cycle mapping (Chainlink stream for 5m/15m/4h, Binance open for 1h, noon-ET 1m close for 1d), the DST-aware boundaries, and the wait-for-close guard into a small async library + CLI:
Polymarket T0 Price-To-Beat Resolver — get the open price the instant the window opens
It covers BTC, ETH, SOL, XRP, DOGE across 5m / 15m / 1h / 4h / 1d, with one dependency (aiohttp).
Good to know
- The source mapping mirrors Polymarket's own settlement logic and was checked against settled markets — in practice the resolved PTB matches the settled value to the precision the site displays. The free scraper covers the after-the-fact read completely; the T0 resolver is for when you need the number at the open.
- You need network access to Binance and Polymarket — some regions block Binance, so use appropriate egress.
- Chainlink ticks at its own cadence; the "first tick at/after the boundary" is the open the platform uses, not a continuous price.
- If Polymarket ever changes a settlement source, the mapping would need updating.
- It returns a price, not a profit — a data primitive, not a trading bot. No orders, no financial advice.
Takeaway
The PTB is reconstructable at T0 as long as you respect three things: the per-cycle source (Chainlink vs Binance open vs Binance close), the noon-ET / DST boundaries for 4h and 1d, and the wait-for-close rule on the daily. Get those right and you have the opening reference price in real time — the one number the API never gives you.