URL Encoding: encodeURI vs encodeURIComponent
Percent-encoding turns special characters into URL-safe sequences. Pick the right function or you will break URLs.
What Is URL Encoding?
URL encoding (percent-encoding) replaces unsafe characters with % followed by their hex code. A space becomes %20, & becomes %26. It ensures URLs are valid and unambiguous. Defined in RFC 3986.
Decision matrix
| You are encoding... | Use | Why |
|---|---|---|
| a single query parameter value | encodeURIComponent | encodes &, =, ?, / |
| a path segment | encodeURIComponent | prevents slashes from changing the path |
| an entire URL | encodeURI | keeps URL structure intact |
| a value you will later decode | decodeURIComponent | reverses percent-encoding for values |
encodeURIComponent
Encodes almost everything: /, ?, &, =, spaces, and more. Use it when encoding a single value that will go in a query parameter or path segment.
const q = encodeURIComponent('hello world & goodbye');
// "hello%20world%20%26%20goodbye"
const url = `https://example.com/search?q=${q}`;
Do not use it for a full URL: it would encode the :// and slashes, breaking the URL.
encodeURI
Leaves URL-structure characters unencoded: /, ?, #, @, etc. Use it when encoding an entire URL but fixing characters like spaces.
encodeURI('https://example.com/path?foo=bar baz')
// "https://example.com/path?foo=bar%20baz"
Do not use it for query parameter values: it would not encode & or =, which can corrupt parameters.
Spaces: %20 vs +
In URLs, spaces are encoded as %20. In application/x-www-form-urlencoded (HTML forms), spaces are often +. Both decode to space. Be consistent: our URL tool uses %20.
Reserved vs unreserved characters
RFC 3986 distinguishes unreserved characters (safe as-is) from reserved characters that have special meaning in URLs.
Unreserved: A-Z a-z 0-9 - _ . ~. Reserved: :/?#[]@!$&'()*+,;=.
When you encode a value that will be inserted into a URL, you usually want reserved characters encoded so they do not change URL structure.
Building query strings safely
Avoid string concatenation for complex query strings. Prefer URLSearchParams which handles encoding rules and edge cases consistently.
Note: URLSearchParams uses + for spaces because it follows form-encoding conventions.
// Safe query-string building
const params = new URLSearchParams([
['q', 'hello world'],
['page', '1'],
]);
const url = '/search?' + params.toString();
// "q=hello+world&page=1" Double Encoding
Encoding already-encoded text produces %2520 instead of %20. Decode once before re-encoding. Double encoding is a common bug when building URLs from user input or from other encoded strings.
Common broken URL patterns
- Unencoded & and =: inserting raw user input into
?q=lets values break into new parameters. - Mixing encoded and unencoded parts: encoding the full URL and then appending parameters usually double-encodes.
- Decoding the wrong layer: decoding a full URL with
decodeURIComponentcan throw if it contains raw%sequences.
decodeURI vs decodeURIComponent
Use decodeURIComponent to decode a value you previously encoded with encodeURIComponent. Use decodeURI to decode a whole URL.
If the input is malformed (bad % sequences), decodeURIComponent throws; handle errors and avoid decoding untrusted strings without validation.
decodeURIComponent('hello%2Fworld%3Fq%3Dtest')
// "hello/world?q=test" When to Encode
Encode any user-controlled or dynamic value that goes in a URL: query parameters, path segments, fragments. Never trust raw input. Improper encoding can lead to open redirects, injection, or broken links.
Testing checklist
- Reserved characters:
&,=,?,#,/,+,% - Unicode (emoji, accents), and mixed scripts
- Empty values and repeated parameters (
foo=1&foo=2) - Very long values (limits differ across systems)
Use the URL Encoder
Encode or decode URLs with encodeURIComponent or encodeURI. Works in your browser.
Open URL Encoder/Decoder