A link that stumps you
https://user:pw@example.com:8080/path/to/page?q=hello%20world&lang=zh#section-2
Seven out of ten people can't enumerate every segment in this URL. It isn't ciphertext—you've simply copied it whole so often you never split it apart. Here is the full anatomy, plus which parts hit the server and which stay in the browser.
The standard anatomy
A canonical URL has up to eight segments (bracketed ones optional):
scheme userinfo host port path query fragment
┌──────┐┌───────┐┌─────────┐┌────┐┌───────────┐┌──────────────┐┌────────┐
https:// user:pw @ example.com :8080 /path/to/page ?q=hello&lang=zh #section-2
└──┴──┘ └──────────────┘
authority
| Segment | Example | Role |
|---|---|---|
| scheme | https |
protocol; sets the default port and encryption |
| userinfo | user:pw |
rarely used; plaintext creds in http, deprecated by browsers |
| host | example.com |
target hostname or IP |
| port | 8080 |
port; defaults to the scheme's when omitted |
| path | /path/to/page |
resource path on the server, /-delimited |
| query | q=hello&lang=zh |
key=value pairs, &-separated, values percent-encoded |
| fragment | #section-2 |
browser-side anchor, never sent to the server |
What reaches the server and what doesn't
This is the most useful split:
server sees: path + query + host + port + scheme
server never sees: fragment (after #) — purely a local browser anchor
Hence:
- query lands in server access logs and analytics; putting sensitive values (tokens, IDs) here is equivalent to intentionally leaking them to logs;
- fragment never reaches the server, so the backend can't authenticate with it—know this trade-off before "hiding a token in the fragment".
Encoding rules for path and query
URLs fundamentally allow only ASCII alphanumerics + . / - _ ~ and a few safe symbols. Everything else (Chinese, spaces, %, &, ?, #, + …) must be percent-encoded:
space → %20
Chinese → each byte as UTF-8, then %xx; e.g. 『中』 = %E4%B8%AD
& → %26 (must be encoded inside a value, or it's read as a separator)
Stop hand-joining URLs: use encodeURIComponent for parameter values and encodeURI for the whole URL. Hand-built strings stumble on some Chinese or special char nine times out of ten.
Common parse pitfalls
- Treating the fragment as a query: nothing after
#triggers a request; a fragment jump only scrolls locally; - Bare
?/#inside a value: an unescaped?or#in a value chops the URL in half; - The
+ambiguity: in a query+often means a space (as inapplication/x-www-form-urlencoded), while in a path it's a literal plus—one character, two meanings; - Default ports depend on the scheme: omitting a port isn't "no port"; parsers fill in 80/443.
Verify each segment with a parser
Don't hunt for delimiters in a long link by eye—throw it into a URL parser tool that lists scheme/host/port/path/query/fragment individually, then compare a normal/anomalous pair. That exposes which segment you assembled wrong. Pair it with a URL encoder/decoder to expand the %xx of Chinese and special chars, and the boundary intuition forms in one go.
Self-check
For this URL, write out its eight segments without a tool:
https://a.com:8443/api/v1/items?tag=dev%20tools&lang=en#top
- Which segments land in server logs?
- What character does
%20represent? - To put a
&inside a query value, how would you write it?
Answer those three and a URL stops being "an unrecognizable string" in your hands.