Short answer: use encodeURI only when you already have a complete URI whose delimiters must remain active. Use encodeURIComponent for one component value, not an assembled URL. Prefer URL and URLSearchParams when constructing browser URLs because those APIs keep data separate from syntax. Neither function is an HTML escaper, a form serializer, or permission to decode repeatedly.
The ECMAScript specification defines two different intentions
The ECMAScript URI handling section says encodeURI and decodeURI are intended for complete URIs. They assume reserved characters have special delimiter meaning. encodeURIComponent and decodeURIComponent are intended for individual components and assume reserved characters are text that must not gain structural meaning.
This distinction is more precise than “one encodes more.” If a search phrase contains &, a whole-URI encoder preserves it and a form-style parser may see a second field. If a return URL contains #, preserving it can move the suffix into the outer URL's fragment. A component encoder turns those data characters into %26 and %23.
Exact characters left unescaped
Both ECMAScript functions leave ASCII letters, digits, underscore, hyphen, period, exclamation mark, tilde, asterisk, apostrophe, and parentheses unescaped. The specification expresses this common set as ASCII word characters plus - . ! ~ * ' ( ). encodeURI additionally preserves ; / ? : @ & = + $ , #.
| Input character class | encodeURI | encodeURIComponent |
|---|---|---|
Letters, digits, _ - . ! ~ * ' ( ) | Preserves | Preserves |
; / ? : @ & = + $ , # | Preserves | Percent-encodes |
| Space | %20 | %20 |
| Non-ASCII scalar value | UTF-8 percent escapes | UTF-8 percent escapes |
A subtle point: RFC 3986 classifies square brackets as reserved, but ECMAScript's encodeURI preserved list does not contain them. The ECMAScript standard itself notes that its reserved set is based on the older RFC 2396 and does not reflect all RFC 3986 changes. Describe actual function behavior instead of claiming that encodeURI preserves every modern reserved character.
A complete URL and one query value are different inputs
const whole = "https://example.com/search?q=red blue#top";
encodeURI(whole);
// https://example.com/search?q=red%20blue#top
const value = "red & blue#top";
encodeURIComponent(value);
// red%20%26%20blue%23topThe first result preserves the scheme colon, slashes, query marker, equals sign, and fragment marker because they are structure in the supplied string. The second protects an ampersand and hash because they belong to one value. Calling encodeURIComponent on the complete address would encode the scheme and separators, producing text that is no longer a directly usable absolute URL.
Calling encodeURI on a user-controlled value is the more dangerous opposite. A value such as safe&admin=true stays structurally active if appended by string concatenation. Component encoding helps, but a structural API is clearer and handles more cases.
Prefer URL and URLSearchParams for composition
const url = new URL("https://example.com/search");
url.searchParams.set("q", "red & blue");
url.searchParams.append("tag", "C++");
url.href;
// https://example.com/search?q=red+%26+blue&tag=C%2B%2BURLSearchParams follows the WHATWG application/x-www-form-urlencoded serializer, so it emits spaces as plus signs. That output is not identical to encodeURIComponent, which emits %20 for a space. Both can convey a space in the correct consumer, but they belong to different algorithms. The %20 versus + guide explains the boundary.
The URL constructor also parses and serializes hosts, ports, relative references, paths, queries, and fragments according to the browser URL Standard. Use the URL Parser to inspect that structure and the Query String Parser to inspect ordered name/value pairs without navigating to the address.
encodeURIComponent is not a strict RFC 3986 encoder
RFC 3986's unreserved set is only letters, digits, hyphen, period, underscore, and tilde. ECMAScript additionally leaves !, apostrophe, parentheses, and * literal for historical compatibility. Many applications accept that output. A signature scheme or protocol that explicitly demands RFC 3986 component encoding may require those five characters to be percent-encoded after encodeURIComponent.
function encodeRfc3986Component(value) {
return encodeURIComponent(value).replace(
/[!'()*]/g,
ch => "%" + ch.charCodeAt(0).toString(16).toUpperCase()
);
}Do not apply that transformation unless the receiving contract calls for it. Browser query construction, OAuth-style signature bases, AWS-style canonical requests, and a custom router can have related but non-identical rules. Name the exact contract instead of inventing one global “strict URL encoding” switch.
Unicode and malformed input can throw URIError
JavaScript strings use UTF-16. The ECMAScript Encode operation throws URIError if it encounters an unpaired surrogate because that code unit is not a Unicode scalar value that can be transformed to valid UTF-8. A well-formed surrogate pair such as an emoji is encoded into four UTF-8 bytes and four percent escapes.
The Decode operation throws for incomplete or non-hex escapes and for byte sequences that are not valid UTF-8, including overlong encodings. Handle failure explicitly. Replacing invalid bytes silently may make a security decision operate on different text than the next component in the request pipeline.
decodeURI and decodeURIComponent mirror the boundary
decodeURI preserves escapes that represent ; / ? : @ & = + $ , #, because decoding them could introduce structure into a complete URI. decodeURIComponent uses an empty preservation set and decodes valid escapes for one component. Neither should be placed in a loop that decodes until no percent signs remain.
For example, one round of component decoding changes %252F to %2F. A second round changes it to a slash. If only the first layer belongs to the current protocol boundary, the second operation changes meaning and may bypass earlier validation. Review double URL encoding before adding fallback decoding.
LiveParse tool behavior and limits
The URL Encoder exposes whole-URI and component choices so the difference is visible; the URL Decoder reports strict decoding errors instead of repeatedly transforming an ambiguous value. Processing runs in the browser and does not send the entered value to a server-side encoding API.
General input is capped at 200,000 UTF-16 code units. URL and base URL fields are capped at 32,768. Parsing a URL is not a network request: the tool does not resolve its host, follow redirects, or fetch the destination. The limits keep an interactive tab responsive and do not claim that a downstream service accepts the same maximum length.
Primary specifications
- ECMAScript encodeURI and encodeURIComponent — normative preserved sets and UTF-8 algorithm.
- WHATWG URL API — browser URL and URLSearchParams behavior.
- RFC 3986 section 2 — modern reserved, unreserved, and percent-encoding definitions.
Want a side-by-side result? Encode the same sample as a complete URI and as a component, then inspect which delimiters remain structural.
Open the URL EncoderFrequently asked questions
What is the main difference between encodeURI and encodeURIComponent?
encodeURI is intended for a complete URI and preserves several structural characters. encodeURIComponent is intended for one component and encodes those characters so data cannot accidentally become separators.
Should I use encodeURIComponent for query parameter values?
It can encode one manually assembled value, but URLSearchParams is usually safer for complete query pairs because it owns separators, repeated keys, and application/x-www-form-urlencoded serialization.
Does encodeURI encode ampersands and hash signs?
No. encodeURI preserves ampersand and hash because they can be URI structure. That makes it unsuitable for untrusted component data that might contain a new query pair or fragment marker.
Is encodeURIComponent exactly the RFC 3986 unreserved set?
No. ECMAScript also leaves exclamation mark, apostrophe, parentheses, and asterisk unescaped for historical compatibility. A protocol requiring strict RFC 3986 component output may encode those five characters afterward.
Why can encodeURI or encodeURIComponent throw URIError?
The ECMAScript Encode operation throws URIError for an unpaired UTF-16 surrogate. Its Decode operation also throws for malformed escapes or percent-encoded bytes that are not valid UTF-8.
Does LiveParse use a server to encode URL components?
No. The URL tools process entered text locally in the browser and do not fetch a parsed destination. General text input is limited to 200,000 UTF-16 code units; complete URL and base fields are limited to 32,768.