A plain-English walkthrough of the encryption and infrastructure controls in the running code. Every claim below describes what the deployed code does today — not what is planned, and not what the underlying library is capable of. Where a protection is weaker than you might assume, it is written down in Known limitations rather than left out.
Every message is encrypted in your browser and stays encrypted for its entire journey. The key is derived from the secret half of your room key — a value that is never sent to us — so the encryption happens entirely on your device, and ours only ever handles the result.
That first layer is a single AES-256-GCM key per room, held for as long as that room's key generation lasts, with a fresh random initialisation vector for every message. On its own it gives you no forward secrecy: someone who obtains a room key can read every message sent in that room under that key. Rotating the key generation — which happens when you revoke a guest — is what puts a hard boundary between an old key and everything after it.
When the two browsers manage to open a direct link to each other, a second layer goes on top of that one. The two devices run a PQXDH key agreement — X25519 plus ML-KEM-768, so a recorded handshake is not decryptable by a future quantum computer either — and then a Triple Ratchet that mints a brand-new AES-256-GCM key for every single message and throws the old one away. Nothing sent over that link touches our servers at all, and a key recovered later does not open the messages that came before it.
The catch is that the second layer only covers the direct link. When that link cannot be established the app falls back to relaying through us under the room key alone, and it is those messages that are stored and readable to anyone holding the room key. That is written up under Known limitations rather than glossed over here.
The app prefers a direct WebRTC data channel between the two browsers. When it is up, messages go straight across it under the ratchet, and our servers never see them — not even as ciphertext, and not as a stored blob.
That channel is deliberately forced through a TURN relay rather than joining the two browsers directly, so neither participant learns the other's IP address. The trade is that the relay provider carries the traffic; it only ever sees encrypted bytes.
When the direct channel is not up — before it finishes negotiating, when a network blocks it, or when the other person is offline — messages fall back to a WebSocket connection to our server, which stores the encrypted blob and forwards it. We hold ciphertext and never the text itself, but we do handle those messages, and we can see the room identifier, message sizes, and when they are sent.
One exception, and it favours you: a large attachment — roughly a megabyte or more — is never handed to the relay while the other person is offline. It stays on your device and is re-sent over the direct channel once you are both connected, so no copy of it ever reaches us. The trade is that it needs you both online at some point, and that is exactly why there is a size threshold rather than a blanket rule: smaller messages and attachments are still left with us and collected later, because holding one of those costs little and the delivery guarantee is worth more.
A room key is two independent halves. The first half is what the server checks you in with, and it only ever stores a one-way hash of it, compared in constant time so it can't leak a partial match through timing. The second half is what every encryption key in your conversation is derived from, and once your key is in your hands, that half is never transmitted to us again.
There used to be an exception here, and there no longer is. Your Owner Key is now generated in your own browser and shown to you before you are sent to the payment page. What travels to us is a one-way hash of the check-in half and nothing else. Paying does not create your key — it activates the one your browser already made. There is no longer a column in our database that could hold a complete key, which is a stronger statement than a promise not to fill one.
A Guest Key carries the room's shared secret inside it, which is how two people reach the same encryption key without that secret passing through us. A room has one guest at a time. Revoking that guest rotates the room's secret outright, so a key you have withdrawn cannot decrypt anything that comes after it, even in the hands of someone who kept a copy of the string.
Only messages that took the relay path are stored at all — anything that crossed the direct channel never reached us. What is stored is the encrypted blob your browser produced, opaque to us either way. Stored messages expire automatically after 7 days, a room holds no more than 5,000 stored blobs at once (delivery receipts and other control frames count toward that alongside messages), and a server-side alarm removes them on that schedule whether or not anyone reopens the room. Revoking a guest deletes them immediately, as part of the same operation.
Alongside the ciphertext we hold operational data that is not encrypted to you: the room identifier, connection slots, push notification subscriptions, and a hash used to admit connections to the room. This is what lets the service route messages at all, and it is described in the privacy policy.
A room ends in one of three ways: you give it a lifetime and that deadline arrives, you destroy it, or you revoke your guest. Any of the three deletes the conversation from our servers. A lifetime can be set when you open a room and extended later in 5/15/30-minute or 1-hour steps, up to a 24-hour ceiling, and that deadline is a real backend alarm — not a timer that stops counting when a tab closes. When it fires, every connection is force-closed and the room's access hash, keys and stored messages are wiped in a single delete.
A lifetime is optional. If you choose no expiry, the room stays available until you destroy it or revoke your guest. Stored messages in a never-expiring room are still swept after 7 days by a separate backstop, so an abandoned room does not keep its contents indefinitely.
Two of the three also clear the other person's device. A room reaching its expiry, and a guest whose key you revoke, both end with that browser erasing its saved copy of the conversation — the moment it learns the room is over, which means the next time it is running and connected. Destroying a room is the one that does not: it purges our stored copy and wipes your own device, but the other participant's browser is never told. See Known limitations.
There's no sign-up, no username, no password, and we never ask for your email address. Access to a room is the key itself: you hold it, we hold a one-way hash of half of it. The only "identity" involved in a session is a random token your browser invents for itself, and it disappears along with everything else when the room ends. There's no user table anywhere to leak.
Payment is handled by Stripe, which keeps its own record of the transaction under its own terms. We keep a record of the payment itself — amount, currency, status and Stripe's reference — because we're required to, for five years, and nothing that identifies you personally.
If you turn on notifications, what travels is a bare category label — "new message," "reaction," and so on — plus the room identifier. Never the message itself. The text you see in the notification is a fixed phrase your own device fills in locally.
Push notifications are delivered by your browser vendor's push service — Google, Apple or Mozilla, depending on the browser. The payload is encrypted to your device, so that service cannot read even the category label or the room identifier. It can see that a notification was sent to your subscription, and when.
The TURN credentials that carry the direct browser-to-browser channel are short-lived and generated fresh for each session — not a fixed secret shipped in the app. There's nothing long-lived to extract from the client even if someone tried. Requesting a set requires the same room authentication as joining the room, so they aren't handed out to anyone who asks.
These credentials exist for the text data channel. BurnerRoom does not have voice or video calling — there is no microphone or camera access anywhere in the app.
Forward secrecy covers the direct link, not the relayed one. The ratchet from webcrypto-ratchet now runs, and every message crossing the direct browser-to-browser channel gets its own key. Anything that falls back to our relay — because the channel hasn't negotiated yet, a network blocks it, or the other person is offline — is protected by the room key alone. For those messages, obtaining a room key retroactively exposes them, including up to 7 days of stored ones. There is no indicator in the app telling you which path a given message took. A large attachment — roughly a megabyte or more — is the one case never exposed this way: it is never relayed while the other person is offline, so it only ever crosses the ratcheted direct channel. Smaller messages and attachments still take the relay path and are still covered by this limitation.
There is no voice or video calling. An earlier version of this page said calls ran over WebRTC. They don't, because the feature does not exist: the app never requests microphone or camera access. WebRTC is used for the text data channel only. If calling is ever built, it will be described here before it ships, not after.
The cryptography is a custom implementation, not an established library. It's built on standard WebCrypto primitives and factored out into its own open-source package (webcrypto-ratchet) so it can be reviewed and reused outside this app — but it is not the audited libsignal library, and it has not had an independent cryptographic audit. Publishing the source isn't the same thing as auditing it.
Destroying a room does not clear the other person's device. Expiry and guest revocation both do: the other browser erases its saved copy as soon as it learns the room is over. "Destroy this room" is different — it purges our stored copy of the ciphertext and wipes your own device, and the other participant's browser is never told, so it keeps whatever it had already received. And in every case, that erasure only happens if their browser is running and connected at the time, or the next time it reconnects. Someone who closes the tab and never returns keeps their copy. We delete ours regardless; we cannot reach a device that isn't listening.
Your saved message history is encrypted, but with a key derived from your room key. Anyone holding your Owner or Guest Key and a copy of your browser's local storage can read your saved history. The encryption protects the data at rest; it does not bind it to a particular device.
We can see that a conversation is happening. Message contents are opaque to us, but room identifiers, message sizes, connection times and message timing are visible to our infrastructure and to Cloudflare, which operates it.
Generated on this device a moment ago. We never receive it, so we cannot show it to you again and cannot recover it. Save it before you continue.
Your key is now active. It opens one private Burner Room on your private chat host.