What Is URL Encoding? The Complete Explanation
URL encoding converts special characters into percent-encoded sequences so they can safely appear in URLs and query strings.
For related fixes and guides, see our troubleshooting hub.
You paste a URL into a browser and it looks normal. You look at the raw HTTP request and the same URL looks like this:
https://example.com/search?q=hello%20world&type=text%2Fplain
That %20 is a space. The %2F is a forward slash. This is URL encoding also called percent encoding.
Why URLs Need Special Character Handling
URLs have a defined syntax. Characters like ?, &, =, #, and / have specific meaning in a URL's structure:
/separates path segments?starts the query string&separates query parameters=assigns values#starts a fragment identifier
If you want to include a literal & in a query parameter value (say, a search for "bread & butter"), you can't write:
/search?q=bread & butter
The URL parser interprets the & as a parameter separator and reads two parameters: q=bread and butter= (with empty value).
URL encoding escapes the & so the parser treats it as part of the value, not as a structural character.
How Percent Encoding Works
Each character is converted to its UTF-8 byte representation, and each byte is written as %XX where XX is the hexadecimal value.
Examples:
| Character | UTF-8 byte | Encoded |
|---|---|---|
| Space | 0x20 | %20 |
& | 0x26 | %26 |
= | 0x3D | %3D |
+ | 0x2B | %2B |
/ | 0x2F | %2F |
? | 0x3F | %3F |
# | 0x23 | %23 |
@ | 0x40 | %40 |
: | 0x3A | %3A |
Non-ASCII characters (accented letters, CJK characters, emoji) are encoded using multiple bytes:
| Character | UTF-8 bytes | Encoded |
|---|---|---|
| é | 0xC3 0xA9 | %C3%A9 |
| 中 | 0xE4 0xB8 0xAD | %E4%B8%AD |
| 😀 | 0xF0 0x9F 0x98 0x80 | %F0%9F%98%80 |
Safe Characters (Never Encoded)
Unreserved characters are passed through unchanged:
- Letters:
A–Z,a–z - Digits:
0–9 -,_,.,~
These are "unreserved" in RFC 3986 they carry no special meaning in any part of a URL.
The + Confusion
+ is a legacy alternative encoding for a space in query strings (from the older application/x-www-form-urlencoded format, used in HTML forms).
So a space can be encoded as either %20 or +, but only in query strings. In URL paths, + is a literal plus sign not a space.
This causes bugs when people assume + always means space or always means plus. The URL encoder/decoder handles this correctly by context.
URL Encoding vs. HTML Encoding
These are different things:
- URL encoding
%XXpercent sequences. For URLs, query strings, API parameters. - HTML encoding
&,<,>, etc. For HTML content, not URLs.
A URL in an HTML attribute needs both:
<a href="https://example.com/search?q=bread+%26+butter">Search</a>
The %26 URL-encodes the &. Inside an HTML attribute, you'd additionally HTML-encode any & that's part of the URL syntax but a formatter handles that automatically.
When You Actually Encode URLs
Building query strings
// Never do this:
const url = `/search?q=${userInput}`;
// Do this:
const url = `/search?q=${encodeURIComponent(userInput)}`;
encodeURIComponent encodes everything except unreserved characters. It's the right function for encoding individual query parameter values.
Don't use encodeURI for query values it intentionally leaves :, /, ?, #, &, and = unencoded because it's meant for encoding a whole URL, not a parameter value.
Fetch/axios requests
Most HTTP libraries handle encoding automatically when you pass parameters as an object:
// The library URL-encodes the params object for you:
fetch('/search?' + new URLSearchParams({ q: 'bread & butter' }))
URLSearchParams handles encoding correctly and is the preferred modern approach.
API documentation
When API docs show a raw URL with special characters, the actual request must use the encoded version. If the docs show:
GET /search?filter=type:image
Your request should be:
GET /search?filter=type%3Aimage
Because : has special meaning in some URL contexts.
Decoding a URL
If you receive an encoded URL and want to read it, the URL encoder/decoder decodes it instantly.
In JavaScript:
decodeURIComponent("bread%20%26%20butter") // "bread & butter"
decodeURI("https%3A%2F%2Fexample.com%2Fsearch") // Wrong decodeURI doesn't decode these
In Python:
from urllib.parse import unquote
unquote("bread%20%26%20butter") # "bread & butter"
What Happens If You Don't Encode
Browsers are forgiving they often encode URLs automatically when you type them in the address bar. But:
- APIs built in code aren't automatically forgiving
- Logs and server access records show literal characters, which can misparse
- Some servers reject requests with unencoded special characters
- Sharing URLs with special characters in messages often breaks the URL at those characters
Full Example
You're building a search URL where the query is C++ programming.
Without encoding: /search?q=C++ programming
With encoding: /search?q=C%2B%2B%20programming
The + signs in C++ become %2B (literal plus in query strings can be ambiguous with the space shorthand). The space becomes %20.
The URL encoder/decoder handles encoding and decoding in both directions. For query string building in code, prefer encodeURIComponent() in JavaScript or urllib.parse.quote() in Python.