When to Use URL Encoding
Query Parameters
When passing user input as query parameters: ``
https://example.com/search?q=hello%20world
`Form Submissions
HTML forms with application/x-www-form-urlencoded encoding use URL encoding.Path Segments
File names or resource identifiers with special characters need encoding.URL Encoding Table
Character Encoded Space %20 ! %21 " %22 # %23 $ %24 & %26 + %2B
JavaScript Methods
encodeURI()- Encode full URLsencodeURIComponent()- Encode URL componentsdecodeURI()- Decode full URLsdecodeURIComponent()- Decode URL components
Percent-Encoding, and Why There Are Two Functions
URL encoding ā percent-encoding, formally ā replaces bytes that cannot appear literally in
a URL with a % followed by two hex digits. A space becomes %20 because a space
terminates the request line in HTTP; an ampersand becomes %26 inside a value because a
literal one would start the next parameter.
The rule that matters is that encoding depends on position. The same character is legal
in one part of a URL and fatal in another:
| Character | In a path | In a query value | In a fragment |
|---|---|---|---|
/ | Separator ā keep | Legal, usually keep | Legal |
? | Must encode | Must encode | Legal |
& | Legal | Must encode | Legal |
= | Legal | Must encode in a value | Legal |
# | Must encode | Must encode | Starts the fragment |
| space | %20 | %20 or + | %20 |
This is why JavaScript ships two functions rather than one. encodeURI() preserves the
characters that give a URL its structure, so it is for encoding a whole URL that is
otherwise well-formed. encodeURIComponent() encodes them, so it is for a single value
being placed *into* a URL.`javascript
const term = 'cats & dogs?';
// Wrong: the & and ? survive and break the query string
/search?q=${encodeURI(term)} // /search?q=cats%20&%20dogs?
// Right: the value is encoded as a value
/search?q=${encodeURIComponent(term)} // /search?q=cats%20%26%20dogs%3F
`
Nine times out of ten you want encodeURIComponent. Reach for encodeURI only when you
are handed a complete URL containing characters that need escaping.
The Plus-Sign Problem
In application/x-www-form-urlencoded ā what an HTML form posts, and what most query
strings are read as ā a space is encoded as +, not %20. Both appear in the wild and
they decode differently:
- decodeURIComponent('a+b')
returnsa+b, nota b. A server parsing form encoding readsa+basa banda%2Bbasa+b.
So a literal plus sign in a value must be encoded as %2B or it will silently become
a space somewhere downstream. This is the single most common URL-encoding bug, and it
surfaces as mangled email addresses and broken search terms rather than as an error.Non-ASCII Is Encoded via UTF-8
There is no character-level encoding for anything above ASCII. The text is encoded to UTF-8
bytes first, then each byte is percent-encoded ā so Ć© becomes %C3%A9 (two bytes, two
escapes) and an emoji becomes four. A decoder that assumes one escape per character
produces mojibake, and a system that percent-encodes Latin-1 bytes produces URLs that no
modern client can read.
Which Tool to Use
[URL encode](/dev/url-encoder/url-encode) ā put text safely into a URL.- [URL decode](/dev/url-encoder/url-decode) ā read an encoded URL back.
- [Percent-encoding](/dev/url-encoder/percent-encoding-tool) ā the character-by-character
view, for working out which escape belongs where.
- [Query string encoder](/dev/url-encoder/query-string-encoder) ā encode a whole set of
parameters at once, with each value escaped independently.Double Encoding
Encoding an already-encoded string turns %20 into %2520, because the % is itself
escaped. This happens whenever a value passes through two layers that each encode
defensively ā a proxy, a redirect chain, a framework that encodes and a template that
encodes again.
The symptom is literal %20 text appearing on a page. The fix is never to decode twice;
it is to find the layer that encoded something already encoded and stop it. Decoding twice
turns a legitimate %2520` in user data into a space and creates a new bug.