URL Encoding Explained: Percent Encoding in Practice
Every developer has encountered a URL that looks like https://example.com/search?q=hello%20world&lang=en and wondered what the %20 means. That's URL encoding — also called percent encoding — and understanding it prevents a class of bugs that appear in form submissions, API calls, redirects, and web scraping code.
What is URL Encoding?
URLs can only contain a limited set of ASCII characters. Many characters that appear in real-world data — spaces, Unicode characters, punctuation — are either forbidden in URLs or have special meaning that would conflict with URL parsing. URL encoding converts these characters into a format that is safe for use in a URL by representing them as a percent sign followed by two hexadecimal digits: %XX.
The specification is defined in RFC 3986. Every character in a URL must either be an unreserved character (which can be used as-is) or must be percent-encoded.
Reserved vs Unreserved Characters
Unreserved characters can always appear in a URL without encoding:
A-Z a-z 0-9 - _ . ~
Reserved characters have special meaning in URL syntax and can only appear unencoded in specific positions. If they appear in data (not as structural delimiters), they must be encoded:
: / ? # [ ] @ ! $ & ' ( ) * + , ; =
All other characters — including spaces, Unicode characters, and most punctuation — must be percent-encoded.
%20 in URLs. In HTML form data (application/x-www-form-urlencoded), spaces are encoded as +. These are different encodings and should not be mixed up.How Percent Encoding Works
To percent-encode a character:
- Convert the character to its UTF-8 byte sequence.
- Express each byte as two uppercase hexadecimal digits preceded by
%.
space → %20 (0x20 in ASCII/UTF-8)
! → %21
" → %22
# → %23
$ → %24
& → %26
/ → %2F
: → %3A
? → %3F
@ → %40
é → %C3%A9 (two bytes: 0xC3 0xA9 in UTF-8)
Note that multi-byte UTF-8 characters produce multiple %XX sequences. The accented character é requires two bytes in UTF-8, so it becomes %C3%A9.
Query Strings vs Path Segments
The rules for URL encoding differ slightly between URL components:
Path segments — the slashes in a URL path are structural, so a / inside a path segment value must be encoded as %2F. Other special characters that aren't reserved in path syntax can often appear unencoded.
Query strings — the part after the ?. Keys and values are separated by = and pairs are separated by &. Any ?, =, or & appearing inside a value must be encoded. Spaces in query strings are often encoded as + by browsers for historical reasons.
# Correct: value with & encoded
https://example.com/search?q=cats+%26+dogs
# Incorrect: unencoded & breaks query parsing
https://example.com/search?q=cats+&+dogs
encodeURIComponent(), in Python use urllib.parse.quote(), in Java use URLEncoder.encode().Common Characters and Their Encodings
space %20 ! %21 " %22 # %23
$ %24 % %25 & %26 ' %27
( %28 ) %29 * %2A + %2B
, %2C / %2F : %3A ; %3B
= %3D ? %3F @ %40 [ %5B
] %5D
Double Encoding Pitfalls
Double encoding happens when already-encoded data gets encoded a second time. A URL like /files/my%20document.pdf contains a correctly encoded space. If a framework re-encodes the path, the % sign gets encoded to %25, producing /files/my%2520document.pdf — which will 404 because the server is looking for a file named literally "my%20document.pdf".
This commonly occurs when passing encoded URLs as query parameter values: the outer URL needs to encode the inner URL's special characters, so a URL-within-a-URL should be encoded with encodeURIComponent() which encodes % signs too.
%25 in a URL where you expected a literal %, you have a double-encoding bug. The %25 sequence decodes to %, which means the original encoding was encoded again.URL Encoding vs Form Encoding
application/x-www-form-urlencoded is the format used when HTML forms are submitted with method="POST" and no enctype set. It is similar to URL query string encoding but with one key difference: spaces are encoded as + rather than %20. This is a legacy behaviour inherited from pre-RFC conventions.
When parsing form data on the server, ensure your parser handles the +-as-space convention. When encoding form data in JavaScript's fetch API, use the URLSearchParams class rather than constructing the body manually.
Encode and Decode URLs Online
The URL Encoder / Decoder at Tools.Fun lets you encode or decode any string for use in URLs. Paste a URL with special characters to encode it, or paste an encoded URL to see the human-readable form. Supports both standard percent encoding and form encoding modes.
← Back