Which Characters Need Percent-Encoding in a URL, and Why
A URL can only safely contain a limited standard set of characters (letters, digits, and a handful of symbols like -, ., _, and ~); anything outside that set — spaces, most punctuation, and non-English characters — must be percent-encoded, replacing the character with a % sign followed by its two-digit hexadecimal byte value, so that every part of the URL is unambiguous and correctly interpreted by browsers and servers.
This restricted character set traces back to the original URL specification, designed to work reliably across many different systems and protocols.
Reserved characters that carry structural meaning
Characters like &, ?, #, and / have specific structural meaning within a URL (separating query parameters, marking a fragment, and so on) — if one of these characters needs to appear as literal data rather than structure (part of a search term, for instance), it must be percent-encoded so it isn't misread as part of the URL's syntax.
Unsafe characters that simply aren't allowed unencoded
Spaces, most punctuation beyond the reserved set, and any non-ASCII character (accented letters, non-English scripts, emoji) aren't valid in a raw URL at all and must be percent-encoded — a space becomes %20, for example, and characters outside the basic ASCII range are encoded based on their UTF-8 byte representation.