encodeURI vs encodeURIComponent: Key Differences, Character Sets, and Pitfalls
A definitive comparison of encodeURI and encodeURIComponent in JavaScript: character escape rules, query parameter handling, and modern URLSearchParams patterns.
The Core Distinction: Protocol vs Parameter
JavaScript provides two built-in global functions for percent-encoding strings: encodeURI() and encodeURIComponent(). While both convert non-ASCII characters into UTF-8 percent-encoded bytes (%HH), they differ critically in how they handle URI reserved delimiter characters (:, /, ?, #, &, =, +, @).
- `encodeURI()`: Designed to encode a complete, full URI. It preserves structural URI syntax characters (e.g.
http://, slashes, query delimiters?and&) while encoding unsafe characters like spaces (%20) and Unicode symbols. - `encodeURIComponent()`: Designed to encode a single query parameter key or value. It escapes structural URI delimiters (
&,=,/,?,#,+) so that user inputs containing special characters do not break the URL structure.
Character Set Comparison Table
The following matrix illustrates which characters are preserved versus escaped by each function:
| Character Category | Characters | encodeURI() Escapes? | encodeURIComponent() Escapes? |
|---|---|---|---|
| Unreserved Alpha-Numeric | A-Z a-z 0-9 | No (Preserved) | No (Preserved) |
| Unreserved Marks | - _ . ! ~ * ' ( ) | No (Preserved) | No (Preserved) |
| URI Delimiters (Reserved) | ; / ? : @ & = + $ , # | No (Preserved) | YES (Escaped: %3B, %2F, %3F, %3A, %40, %26, %3D, %2B, %24, %2C, %23) |
| Spaces | YES (%20) | YES (%20) | |
| Non-ASCII / UTF-8 Unicode | é, 你好, 🚀 | YES (%C3%A9, %E4%BD%A0..., %F0%9F...) | YES (%C3%A9, %E4%BD%A0..., %F0%9F...) |
| Quotes & Angles | " < > \ ` ^ { } | | YES | YES |
Practical Code Examples
Consider constructing an API request URL where the search query is "Salt & Pepper = $5.00":
const query = 'Salt & Pepper = $5.00';
const base = 'https://api.cosharex.com/search';
// WRONG: Using encodeURI on parameters leaves '&', '=', and '$' intact!
const wrongUrl = `${base}?q=${encodeURI(query)}`;
console.log(wrongUrl);
// Output: https://api.cosharex.com/search?q=Salt%20&%20Pepper%20=%20$5.00
// Bug: The server sees two parameters: 'q'='Salt ' and ' Pepper '=' $5.00'
// CORRECT: Using encodeURIComponent on individual query parameters
const correctUrl = `${base}?q=${encodeURIComponent(query)}`;
console.log(correctUrl);
// Output: https://api.cosharex.com/search?q=Salt%20%26%20Pepper%20%3D%20%245.00
// Success: The server correctly decodes 'q' as 'Salt & Pepper = $5.00'The Modern Approach: URL & URLSearchParams
In modern JavaScript (Node.js 18+ and all evergreen browsers), manual string interpolation with encodeURIComponent is largely superseded by the standard URL and URLSearchParams classes, which handle percent-encoding automatically according to WHATWG URL standards:
// Robust, standard-compliant URL construction
const url = new URL('https://api.cosharex.com/v1/search');
// Automatically encodes keys and values properly
url.searchParams.set('q', 'Salt & Pepper = $5.00');
url.searchParams.set('category', 'p2p/files');
url.searchParams.set('page', '1');
console.log(url.toString());
// https://api.cosharex.com/v1/search?q=Salt+%26+Pepper+%3D+%245.00&category=p2p%2Ffiles&page=1Common Developer Pitfalls & Bugs
- Double Encoding Bug: Running
encodeURIComponent()on a string that was already percent-encoded turns%20into%2520. Always encode raw data at the boundary before transmission. - Unescaped Single Quotes: Note that neither
encodeURInorencodeURIComponentescapes single quotes (') or parentheses (()). When injecting values into SQL or HTML attributes, additional escaping is mandatory. - Malformed URI Errors: Calling
decodeURIComponent()on an invalid percent sequence (like"%E0%A4") throws aURIError. Always wrap decoders intry...catchblocks when handling untrusted user input.
Code Formatter & Converter Suite
Validate, format, minify, and convert JSON, SQL, YAML, XML, and code dialects directly on your local machine.
Frequently Asked Questions
Why does URLSearchParams encode spaces as "+" while encodeURIComponent uses "%20"?
Both representations are standard-compliant. `encodeURIComponent` adheres strictly to RFC 3986 percent-encoding (where space is `%20`). `URLSearchParams` follows the `application/x-www-form-urlencoded` mime-type specification, which historically serializes spaces as `+`. Backend decoders seamlessly interpret both formats.
When should I actually use encodeURI() instead of encodeURIComponent()?
Use `encodeURI()` only when you have a pre-assembled, complete URI string that contains unencoded Unicode characters (like `https://example.com/wiki/café`) and you need to convert it into an ASCII-safe URI without breaking the existing protocol or path slashes.
Conclusion
Read more tools and developer guides on CoShareX.
Related Articles
How to Decode and Inspect JSON Web Tokens (JWT): Structure, Base64URL, and Security Traps
A security-focused developer guide on decoding JWTs client-side and server-side, parsing JOSE headers and payload claims, handling multi-byte UTF-8 strings, and avoiding verification anti-patterns.
Developer ToolsHow to Encode and Decode URLs: RFC 3986 Percent-Encoding, URLSearchParams & Polyglot Recipes
Complete guide to URL percent-encoding and decoding: RFC 3986 rules, query string construction, multi-byte UTF-8 handling, and code recipes in JS, Python, Go, and Shell.
ConvertersWhat is Base64? Binary-to-Text Encoding Explained from Bitwise Roots
A deep architectural guide to Base64 encoding: 6-bit binary chunking, ASCII translation tables, padding mathematics, and URL-safe variants.