Every time you type a message in ChatGPT, a silent Cloudflare Turnstile program runs in your browser before your keystrokes register. A researcher just reverse-engineered 377 of these programs and found something that goes way beyond standard browser fingerprinting.
The TL;DR: Cloudflare doesn't just verify you're running a real browser. It verifies you're running a real browser that has fully booted the ChatGPT React application. If your bot doesn't render the actual SPA, it fails. Period.
The Turnstile bytecode arrives encrypted in a field called turnstile.dx — about 28,000 characters of base64 that change on every request.
The outer layer is XOR'd with the p token from the prepare request. Both travel in the same HTTP exchange, so decrypting it is straightforward. Inside sits a 19KB encrypted blob with a twist: the XOR key is embedded right in the bytecode instructions as a float literal.
The full decryption chain requires nothing beyond the HTTP request and response itself. No secrets, no external keys. Just XOR operations on data that's already there.
The decrypted program collects 55 properties across three layers. No variation across 377 samples. Every single time.
6f376b6560133c2c for persistence across page loadsThese are injected server-side by Cloudflare's edge. A bot making direct requests to the origin server behind a non-Cloudflare proxy will produce missing or inconsistent values. It's a built-in authenticity check.
__reactRouterContext, loaderData, clientBootstrapThis is the part that changes the game. These properties only exist if the ChatGPT React application has fully rendered and hydrated. A headless browser that loads the HTML but doesn't execute the JavaScript bundle won't have them. A bot framework that stubs out browser APIs but doesn't actually run React won't have them.
Turnstile is one of three challenges. The Signal Orchestrator installs event listeners for keydown, pointermove, click, scroll, paste, and wheel. It monitors 36 window.__oai_so_* properties tracking:
A behavioral biometric layer running underneath the fingerprint. And there's also a Proof of Work challenge — 25-field fingerprint + SHA-256 hashcash — though 72% solve under 5ms, so it's mostly compute cost, not the real defense.
If you're building anything that interacts with AI APIs, scrapes web apps, or creates browser automations, this is a wake-up call:
__reactRouterContext is an internal structure that makes your app uniquely fingerprintableThe full write-up by the original researcher goes even deeper — covering the custom VM with 28 opcodes, randomized float register addresses, and the entire encryption chain. Worth reading if you're into security.
Building something? I document tools, techniques, and security deep-dives that actually matter. Check out more posts →