~/secret-dm ☕ Support me apps ← about me

Secret DM — a message hidden inside a link that looks broken

The link reads like a crash ID. Whoever opens it lands on a 404 error screen, and the message only appears once they find the easter egg you picked. Add a passphrase and it is encrypted too. Nothing is stored on a server.

compose: bash
$ secret-dm --new
> disguise (what the link looks like)
> easter egg (how they unlock it)

> reveal effect
output
$ echo $LINK
 
# what the recipient sees first

        

Guide — hide a message in a broken link

Everything runs in your browser. The link updates as you type.
1Write the message

Up to 4,000 characters, line breaks and emoji included. Add a passphrase if only one person should be able to read it.

2Pick a disguise

The message is compressed, scrambled and dressed up as a crash ID, a git commit hash, a request ID or a license key.

3Choose the easter egg

A secret shell command, the Konami code, one blinking character in the 404 art, or no egg at all for an automatic reveal.

4Test it as the recipient

Open as recipient opens the link in a new tab, so you see exactly the 404 screen they will see.

5Send the link

Copy or share it. When they find the egg, the terminal recovers your message from lost+found. Send a passphrase through a different channel.

Which option for which message

DISGUISEWhat the link looks like
crash id
ERR-0x… hex in blocks of 8
git sha
sha-… 40-character commit hashes
request id
req-… UUID-shaped groups
license key
key-… groups of 5, the shortest link
EASTER EGGHow they unlock it
command
type the words you chose; case and a leading sudo are ignored
konami
↑ ↑ ↓ ↓ ← → ← → B A, or swipes and two taps on a phone
glyph
click the one flickering character in the 404
none
the terminal recovers the message by itself
PRIVACYHow secret it is
no pass
hidden, not secret: fine for surprises
passphrase
AES-256-GCM, only readable with the passphrase
expires
after 1 hour to 30 days the link shows a segfault
burn
wiped from screen and address bar 30 s after reading
REVEALHow the message appears
typewriter
typed out with a block cursor
matrix
random glyphs settle into your text
hex dump
raw bytes first, then the decoded text

How to send a secret message hidden in a link

A secret DM is a normal web link with your message packed into it. Whoever opens it does not see a message at all: they see a 404 Not Found crash screen with a working fake terminal. The message appears only when they find the easter egg you chose, such as typing cat message.txt, entering the Konami code or clicking a flickering character. With a passphrase the message is encrypted as well, so the link alone is useless.

Where the message lives

Everything sits after the # in the link, the so-called fragment. Browsers never send the fragment to the web server, so there is no database, no account and nothing to leak or delete on our side. The page packs the message like this:

  • the text is compressed with deflate when that makes it shorter;
  • a small header stores the easter egg, the reveal effect, the optional hint, expiry and burn setting;
  • everything is XOR-scrambled with two random bytes, so the same message never gives the same link twice;
  • the bytes are written out as a crash ID, git hash, request ID or license key.

Hidden vs secret: is the message encrypted?

Without a passphrase a secret DM is hidden, not secret. The scrambling stops anyone from reading the message by looking at the link, but anyone who opens the link can find the egg, and anyone who reads the page source can decode it. Use it for surprises, inside jokes and treasure hunts.

With a passphrase the message is properly encrypted in your browser before the link is made. Without the passphrase the link is useless, even to someone who has read this page's source code. It is only as strong as the passphrase, so pick a long one and send it through a different channel than the link.

How the passphrase encryption works

The page uses the browser's built-in Web Crypto API. The passphrase is stretched into a 256-bit key with PBKDF2-SHA-256 and 250,000 iterations, with a fresh random 16-byte salt for every link. The message is then encrypted with AES-256-GCM and a random 12-byte IV. The header with the egg, effect, hint, expiry and burn setting is bound to the ciphertext as authenticated data, so changing any of those in the link makes decryption fail. A wrong passphrase gives "authentication failed". There is no lockout, which is why a long passphrase matters.

Expiry and burn after reading

An expiry of 1 hour, 24 hours, 7 days or 30 days is written into the link. After that moment the recipient sees Segmentation fault (core dumped) instead of the message. Burn after reading wipes the message from the screen 30 seconds after it was revealed and removes the fragment from the address bar.

Both are enforced by the recipient's browser and clock. They stop the casual second look, but they cannot delete the link from a chat history, and without a passphrase a determined person could edit the expiry. For messages that must truly disappear, use a messenger with disappearing messages.

The easter eggs and the fake terminal

The shell command egg defaults to cat message.txt; the 404 then hints "1 file recovered. try 'ls'". Pick any command up to 40 characters and add your own hint of up to 60 characters. Upper and lower case and a leading sudo are ignored. The Konami code works with the arrow keys plus B and A, and on a phone by swiping up, up, down, down, left, right, left, right and tapping twice. The blinking glyph is one character in the big 404 that flickers; clicking or tapping it unlocks the message. With none the terminal crashes and recovers the message by itself after a moment.

The terminal answers help, ls, cat, whoami, pwd, date, uname -a, echo, clear, hint, copy and reply, and has a few answers ready for people who try sudo, rm, exit or vim. After the reveal, copy puts the message on the clipboard and reply opens this page to send one back.

How long can a secret message be?

Up to 4,000 characters. The link grows with the message: with ordinary English text, a 100-character message makes a link of about 240–280 characters, 1,000 characters about 1,070–1,280 and the full 4,000 about 3,500–4,300. The license key disguise gives the shortest link and the request ID the longest; a passphrase adds about 85–100 characters for the salt, IV and authentication tag. The page warns when a link passes 2,000 characters, because some chat apps and SMS cut long links. If a recipient gets "dump corrupted", the link was cut off: send it again or pick a shorter message.

Ideas for using it

Hide a birthday surprise in a link that looks like a bug report. Send your team a "broken" link in Slack where sudo make coffee reveals the Friday plans. Put the link in a QR code at an escape room so the next clue opens on a 404. Or send a colleague a git hash that turns out to be a compliment.

Privacy

The message, the passphrase and the settings never leave your browser: the page does not upload anything, and the fragment is not sent to the server when the link is opened. The page loads its font from Google Fonts and uses SimpleAnalytics, a cookie-free counter that records the page path, not the part after the #.

More fun tools