An ops engineer pastes a one-time link into a Slack channel. A card appears first, titled with the site name. Ten minutes later the recipient opens it and the page says the secret has been burned. Neither side thinks they read the plaintext. The first GET that reached the host was often not a colleague’s finger. It was the chat app fetching a URL so it could draw a preview.
An earlier piece covered why a one-time password link puts the decryption key after #: that is about whether the HTTP host that parks ciphertext can see the key. This piece asks a different question: before anyone clicks, can a preview spend the one read. The key still sits after #. Create and read both open without an account. MyPassGen’s one-time link needs no sign-up. Reads default to 1 and cap at 10. This is not a tour of the create-page buttons. It is a walk through what you can see in Network, the address bar, and the chat window.
Keep two facts apart
Whether a preview burns the ciphertext is not the same question as whether chat history still holds the full URL. A preview that only fetches HTML and never runs page scripts usually cannot read the key after #, and it never reaches the retrieve endpoint. The channel still stores the whole s.html?id=…#… string. Whoever copies it can still open it. A preview that did not burn the secret does not mean the link stopped being a credential.
They say it burned. You never clicked
A common one-time design is: the first retrieve takes the ciphertext, then the server deletes it. When the read limit is 1, that single retrieve is the last copy. Between the sender’s “created” screen and the recipient’s burned state, many visits can land that are not a person clicking: a channel unfurl, a mail security scan, a company gateway that rewrites the URL and then probes it.
Slack writes this into product docs. Unfurling links in messages says that when a user posts a link, Slack fetches the page and attaches a preview. The official robots page names the bot that does that fetch Slackbot-LinkExpanding 1.0 (+https://api.slack.com/robots), and it says the bot fetches as little of the page as it can (using HTTP Range) so it can extract oEmbed, Twitter Card, and Open Graph tags. If those tags point at an image, video, or audio file, it fetches that file too, to check it. Slack Robots also says responses for the same URL are cached across the service for around 30 minutes, and that Slack does not honor robots.txt — the fetch acts on behalf of a user who already posted the URL, not as a site-wide crawler.
So a card already sitting in the channel only proves this: a machine that is not the recipient issued at least one HTTP request to the URL you pasted. It does not prove plaintext was read. It does not prove the ciphertext was counted as a read. To decide whether the secret burned, you have to see which layer that request hit.
Which slice of the URL the preview actually sends
The full link you copy looks like …/s.html?id={id}#{key}. The id after the question mark rides on the HTTP request line. The key after the hash stays on the client, by protocol. See RFC 3986 §3.5 and RFC 9110 §7.1: the target URI excludes the fragment because that slice is for the client. A preview bot issues a normal HTTP GET. A legal request line is GET /en/s.html?id=…. The key after the hash never reaches the machine that parks ciphertext.
That is also why an HTML-only preview usually cannot decrypt the secret. The read page has to let browser script read location.hash, ask the server for ciphertext, then decrypt on this device with AES-256-GCM. A preview crawler has no fragment key — only an id. Even if it stores the full HTML of s.html, that markup does not contain the password. The read page is a noindex landing page. The initial HTML holds a generic title. Plaintext is written into the page only after script finishes.
What the chat app stores is a different object. The user pasted the whole string, hash and key included. Channel search, message sync, and opening the same thread on a new phone still return the full credential. Putting the key after # keeps it off the preview GET and off typical server logs. It does not keep the full URL out of group history. For a more sensitive handoff you can split the id and the key onto two channels — more on that below.
Three kinds of fetch — only one counts
RFC 9110 defines GET as a safe method: sending it should not have destructive side effects. Fetching a page only to draw a card should not, by that semantics, delete ciphertext. In the real world, a one-time tool that treats “first GET of the document” as a read will let a preview bot burn the secret before the recipient arrives. The difference is not the chat app’s name. It is which request the counter is bound to.
Sort fetches by what they can execute. The first kind takes the initial HTML, parses <title> and Open Graph, and never runs page script. Slack’s official description of Link Expanding belongs here: extract meta tags, then fetch media those tags name if needed. Apple’s Ensuring Beautiful Rich Links talk says rich-link generation does not run JavaScript, so Open Graph must live in the page source. Discord channel embeds are commonly produced the same way: Discordbot/2.0 reads the initial HTML instead of opening a full browser engine.
The second kind runs page script, but the request still has no fragment. Headless browsers and some enterprise scan sandboxes sit here. They can execute the read page’s JavaScript and still cannot read location.hash. On this site, no key means no ciphertext retrieve. The page should stop at “Incomplete link.” The read count should not move.
The third kind runs script and loads the full URL — hash included — into a real page environment. A few endpoint-protection products that open “the link you are about to click” in a local WebView, or a preview that fully loads the page on the sender’s device, can reach “retrieve ciphertext and increment the counter.” Protocol does not rule this class out. You can only reproduce it with a test link on the same channel.
Where Slack, WeChat, and mail gateways differ
Slack is the easiest path to check. The official robots page publishes a User-Agent. You can request the read page with that same string and see whether the response is static HTML, and whether the read count later moved. Slack also documents the roughly 30-minute global cache: the same URL pasted into several channels in a short window does not always hit your origin again. A site title on the card only means meta tags or <title> were read. The English read page’s default title is “One-time secret · MyPassGen.” It does not contain your test sentence.
WeChat does not publish a robots page the way Slack does, so you cannot treat an internal crawler’s abilities as a documented contract. What you can see on the spot is: after you paste a URL, does a title card appear; after the recipient clicks, is the read page decrypted, incomplete, or burned. Instant-message cards in that ecosystem are still commonly built by a server fetching HTML title and summary, not by running the read-page script on the recipient’s phone first. With no public spec, trust the result on your test link. Do not treat “a card appeared” as “ciphertext was retrieved.”
Work email is a third path. Microsoft’s Safe Links overview says inbound mail is scanned and URLs may be rewritten; a click is verified again. Rewritten addresses carry a prefix such as safelinks.protection.outlook.com. Delivery-time scans and click-time redirects can both issue another GET at the target. Check two places: whether the body you see is already wrapped, and whether the address bar still holds the slice after # after you click. If the key is dropped in the rewrite or redirect, the read page should say the link is incomplete, not decrypt the secret. If the full URL — hash included — is loaded into a sandbox that runs script, a read can count. Do not assume every gateway “only looks at HTML.” Links in Microsoft Teams channels can also go through Safe Links; the policy depends on the tenant.
Which requests this site’s read page actually makes
After MyPassGen’s read page opens, script does two things in order. First it queries status by id: that request answers whether the secret is still there, already burned, or expired, and it does not increment the read count. With no key after #, it stops there and the page says the link is incomplete. With a key, it then issues the ciphertext GET. That request is the one that increments read_count. When the count hits the limit you set (default 1, maximum 10), the server deletes the ciphertext. The next open is a burned state. Expiry follows the TTL you picked at create: 1 hour, 24 hours, 7 days, or burn-on-read only with no TTL.
So a preview that only GETs s.html?id=…, and a scanner that only hits the status endpoint, do not spend that one read. What spends a read is the ciphertext request issued by “read-page script that already has the key.” At create time the browser encrypts on this device with AES-256-GCM, a 12-byte IV, and a 32 KB plaintext cap. The server parks ciphertext only. The key never enters the HTTP request line. How to check the algorithm and that plaintext was not uploaded is in How to verify that browser encryption did not upload plaintext.
The read page has no separate Reveal button. When the key is present, opening the tab retrieves ciphertext. That does not contradict “preview crawlers only take HTML” — those crawlers usually never reach the retrieve step. The contradiction appears in the third class of fetch: a full URL loaded into an environment that runs script. Then it looks like a person opened the tab, and a default-1 link is spent. You cannot tell the class from the card’s styling. You can only look at status, as in the next section.
A preview that did not burn still leaves a credential in the thread
A full link sitting in a Slack channel, a WeChat chat, or a mail thread is still a credential — only one extra step away from plaintext. Anyone who can search that message can open it before it burns. Closing a private window does not remove a full URL already saved as a bookmark or sitting in Downloads. See After you close Incognito, the password is still in Downloads, bookmarks, and the clipboard.
What is left after a preview
On the same test link, with reads set to 1, the sender and the recipient do not see the same objects after a preview. The table is written in terms of pages you can open, not product slogans.
| What happened | What the chat window usually shows | Opening the full link again should show |
|---|---|---|
| HTML meta only, no script | A title card, no test sentence | Still decrypts the test sentence |
Script ran, but the request had no # |
A card or a blank preview; server saw a status query | Still decrypts; the keyless visit should say incomplete |
| Full URL loaded into an environment that runs script | A card or a scan report; the read was spent | Burned or expired, no plaintext |
| Mail gateway rewrote the URL and dropped the fragment on redirect | A wrapped address such as safelinks… |
Incomplete link; ciphertext is usually still there |
Do not mix the fourth row with the third. If the key was dropped, the recipient cannot open the secret, but the sender can still open the original full URL — the count was not spent; the recipient only has a truncated address. If the key is still there and the page is already burned, a preview or a scan read first. The first case needs a resend of the slice after the hash. The second case needs a new link. There is no server-side plaintext backup, and no support inbox that can recover a burned secret.
Check it on the spot
These steps do not depend on any brand promise. Use a test sentence that cannot log into a real account, for example orange-lake-7. Do not rehearse with a live master password, a production key, or a real one-time link.
- Open One-time, paste the test sentence, set expiry to 24 hours, leave reads at 1, and create the link. Write down the full address and confirm the shape is
s.html?id=…#…. No sign-up. - Copy only the part before the hash. From a terminal, request that URL with Slack’s User-Agent, for example
curl -A "Slackbot-LinkExpanding 1.0 (+https://api.slack.com/robots)" "https://mypassgen.com/en/s.html?id=…". The response should be the read-page HTML. The title or body should not contain the test sentence. This only proves “a document fetch cannot see plaintext.” It does not replace a real chat. - Open the same “id only, no key” address in a browser. You should see Incomplete link, not the secret. Open DevTools Network and enable Preserve log: you should see a status query, and you should not see a later successful ciphertext retrieve.
- Immediately open the full link (with
#) in another tab. It should decrypt the test sentence. If the previous step already burned it, the implementation or a middlebox treated a keyless visit as a read — stop here. Do not send a live secret. - Create another test link with reads set to 1. Paste the full URL into a Slack channel you control, WeChat File Transfer, or a private test group. Wait for a preview card (or confirm there is none). Do not open the read page.
- After the preview appears, open the same full link in a desktop browser. If it still decrypts, the preview on that channel is one of the first two classes. If it is already burned, something in the middle ran the third class — or one of your own devices prefetched the keyed page. Create a new link if you still need to send. After you read, overwrite the clipboard as in Who else can read the clipboard after you copy a password. Do not bookmark an address that still has
#.
For work email, add half a step: send the test link to your own inbox, see whether the body is wrapped as a Safe Links-style address, then see whether the address bar still holds the key after you click. If the key vanished, send the id by mail and the key by phone. If it burned, raise the read count or change the channel. MyPassGen will not classify a vendor’s gateway for you. Trust the windows you just opened.
When you must post into a channel that unfurls
A default of 1 read fits “the other person has the full link, opens it now, then it is gone.” For a channel, a large group, or a mailing list that draws cards, run the previous section on a test link first. Confirm the preview does not count, then send the real secret. If the test already burned, do not expect a higher read count to make the preview “safe.” Raising the limit to 2 only leaves one extra human open. A scanner that runs script every time can still exhaust the count.
A sturdier split uses two channels. One message carries only s.html?id=…. A preview then gets an id and a generic title at most. The other channel — a phone call, in person, or a different messenger account — carries only the slice after #. Neither half decrypts on its own. That is a usage pattern, not a product default. The create page still emits one full link, which is convenient for a one-to-one handoff.
Generate the password on this device. Do not type it into the group and then delete the message. MyPassGen’s password generator uses a random mode of 6–128 characters, default 16, and warns below 8. It opens without an account. The result is not uploaded as business data. A certificate bundle or export larger than 32 KB does not belong on a one-time text link. Use file encryption: streaming AES-256-GCM in the browser, one file up to 5 GB, output .lock / .enc, passphrase sent separately. The cloud store only holds ciphertext. See Before you drop a file in the cloud, who can read the plaintext.
Once you have checked “does the full link still decrypt after the preview” and “does the thread still hold a full credential,” you can answer this article’s question: an HTML-only preview usually does not burn this site’s one-time link first. A fetch that runs script and carries # does. The card itself does not tell you which class you hit. The status page and a second open do.
FAQ
A Slack channel already shows a preview card. Is the link dead?
Not necessarily. Slack’s docs say Link Expanding extracts meta tags and uses Range to take as little of the page as it can. A card only proves the read-page HTML was fetched. Open the full link once more: if it still decrypts, the count is intact; if it is burned, create a new one. Do not keep refreshing the same URL to see if it comes back.
WeChat has no public robots page. Which sentence should you trust?
Trust the result on this test link. A title card only means some program read a title or a summary. Before the recipient clicks, open the full link yourself: if you still see the test sentence, the preview on that channel did not retrieve ciphertext; if it is burned, split the URL or send one-to-one instead.
If you set reads to 2 or 3, does that defeat a preview?
It only leaves extra retrieve slots. It does not turn a preview into a safe method. A scanner that runs script with the key each time can still spend the count. First use a 1-read test link to see whether the preview is one of the first two classes. If you must use an unstable channel, then raise the count and accept that one more person might open it.
Do create and read require an account? Does a preview bot count as a reader?
No sign-up. Create and read are both public to a visitor. A preview bot that only fetches HTML is not a read. If it issues the ciphertext GET, the server cannot tell it from a person, and the count still drops. The read page is public to the recipient. There is no login gate, and no support inbox that can recover a burned secret.