The URL Fragment (#...) That Never Reaches Your Server
Everything after the # in a URL is called the fragment, and browsers never include it in the HTTP request — not in the request line, not in any header. It's not a privacy feature that was deliberately bolted on; it's a 30-year-old consequence of what a fragment was originally for, that OAuth, client-side routers, and this site's own share-pad now lean on deliberately.
// the anatomy of a URL
// verified with a real capture, not just the spec
This is easy to confirm yourself: open any page with something in the hash, open your browser's devtools Network tab, and reload. You will not find the fragment in the request URL of the page load itself, nor in any request the page makes afterward — because the browser never had it to send. Loading https://toolsharp.dev/tools/share-pad#data=SECRET_VALUE with a network log attached shows exactly this: the page-load request goes out as GET /tools/share-pad, with no trace of SECRET_VALUE anywhere in the 14 requests that page makes — while window.location.hash still reports the full value back to any script running on the page. Nothing was hidden from JavaScript; it was hidden from the network.
// why this exists
The fragment predates any privacy use case entirely. In the original HTTP/URL design, a fragment like #introduction identifies a location within a resource the browser has already retrieved — the classic "jump to this heading on the page" anchor link. Since it only makes sense once the full page is already loaded, it was never part of what gets sent to ask for that page in the first place. That's a structural fact from how the URL specification separates "identify a resource" from "identify a piece of that resource" — not a feature anyone added on purpose for privacy. Developers noticed the side effect and started building on it deliberately.
// what actually relies on this today
- OAuth 2.0 implicit flow — returns the access token appended to the redirect URL's fragment specifically so it never lands in the redirect target's server logs. (Implicit flow is now discouraged in favor of Authorization Code + PKCE, for other reasons — token lifetime and same-page script exposure — but the redirect step still works this way because of exactly this behavior.)
- Client-side routers — older single-page apps (early Angular, hash-mode React Router) used
#/users/42-style routes precisely because changing the fragment doesn't trigger a full page reload or a new server request — the app's own JavaScript reads the change and re-renders. - This site's share-pad — the offline-link mode compresses your text directly into the fragment. The tool page can decompress and display it purely from
window.location.hash— the text was never sent to ToolSharp's server, or anywhere else, to produce that link.
// where the guarantee ends
"Never sent to the server" is a specific, narrow guarantee — not a general statement that the data is secret. It's worth being precise about what it does and doesn't cover:
- Any JavaScript on the page can read it.
window.location.hashis a normal DOM property — the page's own script, any third-party script it loads (ads, analytics, a chat widget), and any browser extension with page access can all read it freely. The guarantee is about the network, not about code running in the browser. - It still leaves outbound in one place: your own history. Your browser stores the full URL, fragment included, in local history — and if browser sync is turned on, that history (fragment included) can sync to your browser vendor's account.
- The
Refererheader is fragment-free too — which helps. If a page with a sensitive fragment contains a link to somewhere else, the outboundRefererheader sent to that destination is defined to exclude the fragment. That's one fewer leak path, not an exception to watch for. - Copying the link still copies the data. If you paste the full URL into a chat, an email, or a bug report, the fragment goes with it as plain text. The guarantee is "your server's access logs won't have it" — not "this data can't end up anywhere."
// try it yourself
Generate an offline share link with share-pad, open your browser's devtools, and watch the Network tab as the link loads: the text you shared never appears in a single request. That's this exact mechanism, not a special case built just for that tool.
A URL has a part the server receives and a part it doesn't. Everything up to and including the query string goes out over the network in the request line. The fragment — everything from the
#onward — is stripped off by the browser before the request is even built. The server hosting the page has no way to see it, because it was never sent.