Your login link was already clicked.
Mail security fetches every URL in an inbound email before your user ever sees it. The fix isn't a smarter bot heuristic. It's deciding what your token is actually bound to.
A user asks for a login link. Before the email reaches their inbox, their employer's mail security has already clicked it. They open the mail, click, and are told "This link has already been used."
They do not say "my mail scanner ate my link." They say "your login is broken." And mostly, they say it to nobody at all — they close the tab and go and do something else with their afternoon.
This is a bug whose entire failure mode is invisible to the people who caused it. Your logs show a successful redemption. Your metrics show a click. The only person who knows something went wrong is the one who couldn't get in, and they have no vocabulary to describe it and no reason to try.
What is actually happening
Microsoft Defender Safe Links scans URLs before the message is delivered, and detonates anything without an established reputation asynchronously in the background. Mimecast has done pre-delivery scanning by default since late 2025, for URLs its risk classifier flags. Proofpoint does it on the Threat Protection tier. Others, including Barracuda, verify at click time instead, which moves the problem rather than removing it.
They fetch from datacentre ranges and present ordinary browser user-agent strings, and several of them say plainly in their own documentation that they anonymise their scanners on purpose — because a malicious page that can detect the scanner is a malicious page that can hide from it.
You can sometimes still tell. Akamai's researchers fingerprinted a range of these products and found every one of them leaking something: spoofed user-agents claiming Internet Explorer 6, hard-coded Referer values, PTR records pointing straight back at the vendor. So it is not that detection is impossible. It is that there is no stable, supported signal to filter on, the vendors are actively working against you, and building your login flow on the winning side of a fingerprinting arms race is not a plan. IP filtering is worse: you would be maintaining the published ranges of every mail security vendor on earth, forever.
There is an irony worth noticing on the way past. The same fetches inflate the click-through rates in your email dashboard. A good part of this industry has spent years celebrating engagement metrics generated by antivirus software.
And it is not only enterprise mail. Slack, Teams and Discord unfurl links to build a preview card. iOS Mail and Outlook fetch for previews. Browsers prerender. Every one of them will happily burn a single-use GET token, and none of them think they are doing anything wrong.
This is our fault, not theirs
It is tempting to file this under "enterprise IT breaks things." It isn't. The scanners are doing something reasonable, and we are the ones violating a rule that has been in the specification for decades.
RFC 9110 §9.2.1 defines a class of request methods as safe: "Request methods are considered safe if their defined semantics are essentially read-only; i.e., the client does not request, and does not expect, any state change on the origin server as a result of applying a safe method to a target resource." GET is on that list. The specification goes further and says the quiet part explicitly — a safe method may still cause side effects, but "the client did not request that additional behavior and cannot be held accountable for it."
That is the whole article in one sentence. If a GET burns your single-use token, the client cannot be held accountable for it. The scanner is not misbehaving. We built a state change into a method that promises not to have one, and the environment has finally sent us the invoice.
Every fix that follows is a way of moving the state change off the GET.
The question is what the token is bound to
There are four common answers, and they are usually presented as a progression from old-fashioned to modern. That framing is wrong, and it is the reason most teams pick badly. They are not a ladder. They are four different answers to one question: what is this token bound to?
A typed code can be bound to the session that requested it, if you implement it that way — plenty of implementations bind to the account instead, which is weaker. Done properly, the code travels through the human, which makes it device-agnostic for free. Cloudflare Access uses a one-time PIN, and Cloudflare's own documentation acknowledges that third-party mail security can consume a login link before the user gets to it. The weakness is the one everybody knows: a code can be talked out of a person. Real-time relay phishing exists precisely because the human is the transport.
A time-boxed, multi-use link is bound to a clock and nothing else. Stop burning it on fetch, expire it on a timer. Honest and simple: the exposure window is the TTL, and that is the entire trade.
An interstitial is bound to nothing, but it moves the redemption to a POST. You land on a page with a button, the scanner fetches and does not submit, and everybody pays one extra click.
A URL fragment is bound to nothing at all. It hides the token from the scanner rather than binding it to anyone. It is the interesting one, and the one almost nobody writes about properly.
The fragment, explained properly
When I looked at Anthropic's sign-in email in August 2026, it pointed at claude.ai/magic-link#<token>:<base64 email>. Note the #, not a ?.
RFC 3986 §3.5 defines the fragment as being "dereferenced solely by the user agent, regardless of the URI scheme." Its original job is #section-2 — telling your browser where to scroll, which is none of the server's business. RFC 9110 §7.1 makes the consequence explicit: "The target URI excludes the reference's fragment component, if any, since fragment identifiers are reserved for client-side processing."
So the fragment does not travel in the navigation request. When a scanner fetches that URL, what arrives at the origin carries no token: not in the request line, not in your access logs, not in your CDN's logs, and not in the Referer of anything the page subsequently loads — RFC 9110 §10.1.3 requires user agents to strip the fragment when generating Referer. The token reaches the server only when the page's own JavaScript reads window.location.hash and sends it deliberately. A plain GET cannot burn it, because a plain GET never sees it.
Credit where it is due: that is elegant, and the entire mechanism is one character.
It is narrower than "never transmitted," though, and the difference matters. Defender Safe Links rewrites the href and encodes the original URL — fragment included — as a query parameter of safelinks.protection.outlook.com. The token does travel. It travels to Microsoft, and into Microsoft's logs. What the fragment buys you is that it stays out of your logs and out of the request that would have burned it. That is a real property. It is not invisibility.
One more detail worth noticing. The button in that email carries clicktracking=off, the attribute SendGrid documents for opting a link out of its click-tracking redirector, which every other link in the message passes through. It is tempting to call that belt-and-braces on the grounds that fragments survive redirects anyway — RFC 9110 §10.2.2 does require a Location without its own fragment to inherit the original's. But that rule is about redirects, and click tracking is not a redirect: the href is rewritten in the HTML at send time, before any request exists. Whether the fragment survives depends entirely on whether the rewriter preserved it inside the encoded URL. So the opt-out may well be load-bearing, and if it is not there, the token lands in a tracking query string.
What the fragment does not do
A scanner that drives a real browser walks straight through it. The rewriter parses the whole href, so the fragment survives; render the page, let its JavaScript run, and the token is redeemed exactly as if a person had arrived.
That makes the fragment a probabilistic defence rather than a structural one. It works because most delivery-time checking is a cheap HTTP GET, and full detonation is expensive and rationed — Microsoft's stated trigger is URL reputation, and a DKIM-signed transactional message from an established sending domain is not where that budget goes. It stops the common case for almost nothing. It is not designed to stop the determined case, and it doesn't.
There is a second exposure, and it is the more interesting one. A token in a fragment is a bearer credential for the whole of its life. Anyone who obtains the URL can spend it: a forwarded email, a shared screen, a mail archive, a support ticket with a pasted link, browser history synced across devices, an error-reporting SDK that captures location.href by default. The design assumes nothing untrusted ever runs on that page.
OAuth learned a version of this in public. RFC 9700, the Best Current Practice for OAuth 2.0 Security published in early 2025, tells clients they SHOULD NOT use the implicit grant, and access tokens sitting in fragments — reachable from browser history and from any script on the page — are part of the reason. Its §4.1.2 attack turns on exactly the redirect-inheritance rule described above. RFC 9110 carries its own warning in §17.11, "Disclosure of Fragment after Redirects."
I want to be careful with that analogy, because it is not exact, and the differences all cut the same way. OAuth was putting reusable, longer-lived access tokens in fragments; a magic-link token is single-use and short-lived, so the blast radius is much smaller. The deprecation was also driven by open-redirector and token-injection attacks that have no equivalent here. The exposure mechanism rhymes. The consequences do not. Anyone citing RFC 9700 as proof that fragments are simply wrong is overreading it, and I do not want to be that person.
And one honest limit on everything above: an email shows you the URL and nothing else. I can see that the token is in the fragment. I cannot see what Anthropic checks when it arrives — whether there is a session cookie, a device binding, rate limiting by ASN, or anything else behind it. Nothing here should be read as a claim that the fragment is their only defence, because that is not a claim the evidence supports.
What we do, and why
We bind the link to the browser that asked for it. When a user requests a login, we set a nonce in a cookie in that browser session, and at redemption we check that the nonce presented matches the one recorded against that specific token.
That last part is the whole thing, and it is worth being precise about, because the obvious implementation is wrong. If you check only that some valid nonce is present, an attacker who obtains the emailed URL simply requests their own login first, collects their own cookie, and redeems your token in their browser. The binding has to be token-to-nonce, not merely "a nonce exists."
The cookie is Secure and HttpOnly, but the attribute that decides whether any of this works is SameSite, and it has to be Lax. A click from a webmail client is a cross-site top-level navigation; Strict withholds the cookie and breaks the flow completely, on every click, for everyone.
Get that right and a scanner cannot redeem the link, because it cannot hold a cookie that was set in someone else's browser. Not with more patience, not with a real Chrome. The honest exception is remote browser isolation — where the "browser" holding the user's cookies is a container the enterprise operates, and a scanning layer inside that path is inside the cookie jar. It is rare, and if your customers run it you will know.
That is still a different class of guarantee. The fragment defends against the scanner. The cookie defends against anyone holding the URL. Those are different threat models, and which one you need is a decision about your product, not a question with a universally correct answer.
The obvious objection is that cookie binding breaks the request-on-desktop, open-on-phone flow. It does, and that objection is why most teams don't do it. But the cost is smaller than it looks, because the failure has a good answer.
If the link opens somewhere without the nonce, we don't say no. We land the user on a page that says: ask for a new one from here. One click, a fresh email, and it works — because now the cookie is in the browser they are actually using. The cross-device case costs one extra round trip, and the people most likely to hit it are the people most comfortable resolving it.
And the cross-device framing understates the problem it solves. It is not only about moving between devices. It is about browser profiles. Users with several accounts at different privilege levels keep them in separate profiles and private windows, deliberately. Their mail client opens the default browser, which is by definition the wrong session — on the same machine. A link that only works where it was requested is not just more secure there. It is more likely to land the user in the right account.
Where we deliberately do the opposite
We have flows where we do not check the nonce and do not burn the token on the first click. That is not an oversight. It is the same reasoning, applied to a different risk.
Send someone a contract to sign, and the scenario changes completely. That link has to survive a mail scanner, possibly one that runs a real browser. It has to survive being forwarded to a colleague, opened on a phone, and clicked again three days later. The signer getting in matters more than the marginal risk of someone else seeing the document, because a counterparty locked out of their own contract is a worse outcome, commercially and reputationally, than the interception you just priced in.
Same codebase, opposite defaults, and both are correct. Security is not a score you maximise. It is a set of risks you accept on purpose, in writing, per flow. The mistake is not picking the weaker option. The mistake is picking either one globally and never revisiting it.
Three things worth doing on Monday
Stop burning the token on a failed check. If the nonce is missing or wrong, refuse without spending it. That single change turns a permanent lockout into a retry, and it is correct whichever scheme you eventually choose. It is not free, and I should say what it costs: a token that survives failed attempts is a live credential sitting in an inbox for its full TTL, with unlimited tries against it. So cap the attempts per token and keep the TTL short. Trade made on purpose, which is the entire argument of this piece.
Decide per flow, not globally. These links are not worth the same. A link into a shared document should prioritise the reader getting in — lock them out and they don't file a ticket, they conclude your product is broken. A link that hands back account access should prioritise nobody else getting in.
Say something true on the failure page. "This link has already been used" is, in this scenario, a lie told to the one person who didn't use it. Tell them what actually happened and give them the button that fixes it. That page is not an error state. It is the last chance you get.
And a tip for the other side of it, with its own explanation attached. If a magic link tells you it has already been used, try copying it and pasting it into the browser you originally asked from. If the token really was burned by a scanner, nothing will save it. But if the site is cookie-binding and simply mislabelled a missing-cookie failure as "already used" — which, on the evidence of that error message, plenty of them do — then arriving in the right browser is exactly what it wanted, and you are in. That the trick works at all is a symptom of the third problem above.
None of this is exotic. It is one question, asked early: what is this token bound to? Answer it deliberately and every other decision falls out. Answer it by accident, and you will find out from a user who never told you.
Vela Intelligence builds decision intelligence infrastructure for regulated, high-stakes environments — where the difference between a link that fails safe and a link that fails silent is the kind of thing that ends up in an audit. For strategic conversations, contact contact@velaintelligence.com.