Because of a limitation in iPhone's browser, this file only works when opened from a secure, hosted address — not when opened directly from Files or Downloads.
Open the hosted version →Cherry2Cherry is a minimal peer-to-peer chat. When you connect to someone, your two browsers open a direct WebRTC data channel and messages travel straight between them — not through a chat server.
On top of the connection, each browser generates a fresh key pair for the session (X25519, via the NaCl box construction). The two sides exchange public keys and every message is encrypted before it leaves your device, then decrypted only on the other side. Keys are generated new each session and never leave your browser.
The code currently contains no part that gives any person, company, or authority a way to see your messages before they're encrypted. There is no scanning, logging, or reporting step anywhere in the message path — you can verify this yourself by reading the source, it's a single plain HTML file.
A "safety number" is shown once a connection is encrypted — a short code derived from both public keys. Read it out to the other person over a phone call or in person. If it matches on both screens, the connection hasn't been intercepted or swapped by anyone in between, including the signaling server.
This is unaudited, hand-built encryption — treat it as a solid prototype, not a substitute for audited tools when the stakes are high.
It also can't protect against scanning that happens before encryption, on the device itself, if that were ever legally required of an app. That's a policy question, not something any amount of client-side cryptography can technically prevent, because such scanning would need to be built into the app's own code to comply.
As of mid-2026, an interim EU rule ("Chat Control 1.0") lets platforms voluntarily scan unencrypted messages, reinstated July 2026 and running until 2028 — end-to-end encrypted traffic like this app's is explicitly outside that scope. A separate, permanent regulation ("Chat Control 2.0", formally the CSAR) is still being negotiated, not adopted, with talks resuming in September 2026. This section is about that second, unresolved one, since it's the one that could someday touch encryption.
It would very likely not mean automatic, blanket scanning. The European Parliament's negotiating position centers on targeted, judicially-authorized "detection orders" against specific, identified providers — not a rule that every app must silently build in scanning. Whether Cherry2Cherry could ever realistically be targeted by such an order is a separate, open question — but a global "must scan everything" mandate is not what's currently on the table.
A copy you already have can't be changed by a future law. Any copy of this file that already exists — downloaded, burned to a CD, wherever — is just static bytes. No regulation can reach back and alter code that's already sitting on your device; a legal requirement, if one ever applied, could only affect future versions someone chooses to build and distribute.
A tool with no ongoing operator is an odd fit for this kind of order. Detection orders target a "provider" actively running a service. Once you've downloaded this file, there's no server, account, or ongoing operation left for anyone to compel — the developer's involvement effectively ends at the point you got the file. That doesn't guarantee anything, since the final legal text (and how broadly "provider" ends up defined) isn't settled, but it's a real structural difference from a hosted platform.
None of this is legal advice — it's a factual summary of where things stand as of this writing, on a topic that's still actively moving. If it matters for your specific situation, check current sources or talk to a lawyer.
Only you and the person you're connected to can read message content. A public broker server is used once, at the start, purely to help two IDs find each other and exchange public keys — it never sees plaintext.
The image button in the composer compresses a photo in your browser before sending it — resized and re-encoded, then encrypted the same way as text messages. Very large or complex images may be rejected if they're still too big after compression; try a smaller photo in that case.
"Save to browser" keeps a decrypted copy on your own device only, using local browser storage. "Download as file" saves a plain text transcript to your device (images show up as "[image]" there, since a text file can't hold a picture). Neither sends anything anywhere. Saved images do take up more local storage space than text — if you save many image-heavy chats, you may eventually hit your browser's storage limit for this page. You can tag any chat with an emoji — the small box next to "Chatting with…", or the badge on each entry in Saved chats — purely to help you recognize conversations at a glance, since peer IDs themselves are random and reset every session. If you'd rather leave nothing behind at all — say, running this off a USB drive or a CD on a computer that isn't yours — the "Clear history on close" switch on the Me tab deletes saved chats and the activity log the moment you close the tab. It's off by default, since it's a deliberate one-way action.
The circle at the top of the Me tab is just an emoji on a solid color — tap it to change either. Nothing is uploaded, and it's never sent to anyone you connect with (this app has no concept of exchanging profile data at all); it's stored locally in your browser and stays exactly as you set it until you change it again.
The "Full screen" switch on the Me tab hides the browser's own address bar and chrome, using the browser's standard Fullscreen API. It's available on both desktop and mobile. Since browsers only allow entering full screen as the direct result of a real tap or click, if you leave it on, the next time you open the app you'll see a "Continue" button on the loading screen — tapping it is what actually triggers full screen, right as it dismisses the splash.
This is a single self-contained HTML file. It doesn't need GitHub Pages, a domain, or any hosting — you can just hand the file itself to whoever you're chatting with.
Easiest way: double-click cherry2cherry.html and it opens directly in your browser (Chrome, Firefox, Edge, Safari all work). Each person keeps their own copy of the file on their own device — nobody needs to upload or serve it anywhere.
One catch: some browsers restrict clipboard access (the "copy ID" click) and similar features when a page is opened directly as a local file (file://) rather than served over http://. If copy-to-clipboard doesn't work, just select and copy the ID text manually — everything else still works.
If you want full compatibility: serve the file from a tiny local web server instead of opening it directly. This still runs entirely on your machine, nothing is exposed to the internet:
# In the folder containing cherry2cherry.html: # Python (usually already installed, Mac/Linux/Windows): python3 -m http.server 8000 # then open http://localhost:8000/cherry2cherry.html # Node.js alternative, no install needed: npx serve .
Either way, online mode still briefly needs the internet, on both sides: the first handshake that lets two IDs find each other uses a public signaling service (the PeerJS broker). That's exactly what offline mode removes.
The "Switch to offline mode" button turns off all networking this app does on its own — no broker, no STUN server, nothing. Instead, the two browsers exchange a short connection code by hand: one side creates an invite code, the other pastes it in and generates a response code, which goes back to the first side. How you send those codes — AirDrop, a message, reading them out loud — is entirely up to you and happens outside the app.
The honest limitation: without a STUN server, this reliably works when both devices are on the same local network (same Wi-Fi). Across two different networks — say, one phone on mobile data and another on a different Wi-Fi — a direct connection will very likely fail to establish. That isn't a bug in this app; it's how home and mobile routers handle unsolicited incoming connections (NAT), and no client-side software can fully work around it without some external rendezvous service — which is precisely what offline mode removes.
Don't just take that on faith — the Me tab lists every single network call this page makes, by name, driven by the browser's own performance and WebSocket APIs, not by this app claiming anything about itself. Switch to offline mode and watch it: nothing new should ever appear for the rest of the session.
WebRTC (used by both online and offline mode) only works in what browsers call a "secure context" — a page served over https://, or over http://localhost. Safari on iOS enforces this strictly: opening this file directly (file://…) means anything relying on WebRTC will silently do nothing, with no visible error. A warning banner appears automatically at the top of the page when this is detected.
This is a WebKit/Safari platform rule, not something fixable in this file's code. On iOS, the practical options are: run a small local web server directly on the phone (there are free "local server" apps in the App Store) and open http://localhost:PORT/cherry2cherry.html, or host the file anywhere over https://, even briefly. Desktop browsers (Chrome, Firefox, Edge) are more lenient with local files and usually work fine either way.
Since this is one self-contained file, a burned CD works exactly like any other copy: insert the disc and open cherry2cherry.html from it in your browser (double-click, or drag it into an open browser window). On Windows or Mac, this behaves the same as opening it from a folder on your desktop — online mode, offline mode, and encryption all work normally on desktop browsers.
The one thing to know: a CD is read-only, so nothing the app does — saved chats, the activity log, your theme choice — can be written back to the disc. Anything you save gets stored in the browser on whichever computer you're using at the time, same as running from any other local file. If you don't want any trace left on that computer afterward, turn on "Clear history on close" on the Me tab before you start — it wipes saved chats and the activity log the moment you close the tab.
A finalized CD also can't be silently modified after the fact — unlike a file sitting on a server or a shared drive, changing what's on the disc means physically burning a new one. Pair that with the checksum check on the Me tab (the "With file" mode works great here — point it straight at the file on the disc) and a CD copy is about as tamper-evident as this app gets.
Worth knowing: a browser genuinely can't tell whether a file it opened came from a CD, a USB stick, or an ordinary folder — there's no web API for that, on purpose, for privacy reasons. When you open this from any local file, a reminder about "Clear history on close" appears on the Me tab as a nudge, not a real detection. If you want it on by default instead of having to remember, there's a separate CD-specific build (cherry2cherry-cd.html) that starts with "Clear history on close" already switched on.
If you didn't get this file directly from the official page, you can check it hasn't been altered: the official checksum (SHA-256) for each release is published on the Cherry2Cherry landing page — deliberately not inside this file itself, since a tampered copy could otherwise just display a matching fake checksum. If your copy's checksum doesn't match exactly, don't run it.
Older releases stay verifiable too — the landing page keeps previous versions' checksums listed under "Previous versions," and the checker on the Me tab recognizes them as well, not just the current release. So a copy from an earlier version — a CD burned a while back, say — will correctly show as genuine, just labeled with its own version number instead of the latest one.
The Me tab has a checker with two modes: With URL fetches this page's own bytes automatically, but only works on the hosted version — a local file can't fetch its own bytes. With file works everywhere, including this local copy — it opens a file picker, reads the .html file straight off disk, and computes the checksum from that, no network required for that part.
Let the other person scan this with their camera instead of typing or pasting your ID.
Stored only on this device — never sent to anyone you chat with.