A URL (uniform resource locator) is an address with up to seven parts. The part after the ? is the query string, a list of key=value pairs that passes small amounts of data to the server. Because a few characters have special meaning inside a URL, anything else that contains them must be percent-encoded.
Anatomy of a URL
Take this address:
https://[email protected]:8443/shop/shoes?q=red+shoes&size=9&tag=a&tag=b#reviews
| Part | Value | Notes |
|---|---|---|
| Scheme | https |
Which protocol to use |
| Userinfo | user |
Rare, and best avoided |
| Host | www.example.com |
Which server; case-insensitive |
| Port | 8443 |
Defaults: 80 for HTTP, 443 for HTTPS |
| Path | /shop/shoes |
Which resource on the server |
| Query | q=red+shoes&size=9&tag=a&tag=b |
Parameters, after ? |
| Fragment | reviews |
A spot within the page; never sent to the server |
Paste any address into the URL Parser to see these parts and every query parameter listed separately.
Percent-encoding
Reserved characters have jobs in a URL: ? starts the query, & separates pairs, = separates key from value, # starts the fragment, / separates path segments. To use one as plain data, write % followed by its byte value in hexadecimal. Characters outside ASCII are first turned into UTF-8 bytes, and each byte is encoded.
| Character | Encoded |
|---|---|
| space | %20 (or + in form-encoded queries) |
# |
%23 |
& |
%26 |
= |
%3D |
? |
%3F |
/ |
%2F |
% |
%25 |
é |
%C3%A9 |
€ |
%E2%82%AC |
Encode and decode text with the URL Encode and URL Decode. Note that % itself must be encoded as %25, which is why decoding twice breaks values.
Query strings
Pairs are separated by &. The same key can repeat, and receivers decide how to read it. Parsing the query above gives:
| Key | Values |
|---|---|
q |
red shoes |
size |
9 |
tag |
a, b (the key appears twice) |
To build a correctly encoded query, enter the pairs into the Query String Builder. For example, the values red shoes & boots and 10-20 become q=red+shoes+%26+boots&price=10-20. Campaign tags are an application of the same idea: see How to Build UTM Links for Campaign Tracking.
International domain names
Hostnames travel as ASCII. A name with accented or non-Latin letters is converted to punycode and prefixed with xn--: münchen.de becomes xn--mnchen-3ya.de. Look-alike letters from other alphabets make the same mechanism a favourite of phishers, so convert suspicious hosts with the Hostname to Punycode Converter.
Common pitfalls
- Forgetting to encode a value. An unescaped
&or#in a value silently cuts it off. - Double encoding. Encoding an already-encoded string turns
%20into%2520. - Putting secrets in the URL. Query strings end up in logs, history and referrer headers.
- Assuming one value per key. Read repeated keys as lists.
- Trusting the visible part of a link. See How to Analyze a Suspicious Link Safely.