encodeURI or encodeURIComponent? One Rule That Works
The two differ by eleven characters, and picking wrong either breaks the URL or corrupts the value. Here is the rule, and the plus-sign trap.
· 3 min read
A URL is not a string; it is a structure. Slashes separate path segments, a question mark starts the query, an ampersand separates parameters, and a hash begins the fragment. Percent-encoding exists so that a value can contain one of those characters without being mistaken for the structure. The two encoding functions differ on exactly one question: are you encoding the structure, or something going inside it?
The rule
Use encodeURIComponent for a piece that goes into a URL, and encodeURI for a whole URL that is already assembled. In practice you almost always want the first one, because the second is only correct in a narrow case: you have a complete, structurally valid URL containing illegal characters — a space in a path, say — and you want it made legal without disturbing the structure.
The difference is that encodeURI deliberately leaves the reserved characters alone, because in a whole URL they are doing their job. encodeURIComponent escapes them, because in a value they are not.
const value = 'a/b?c=d&e';
encodeURI(value); // 'a/b?c=d&e' unchanged, still structural
encodeURIComponent(value); // 'a%2Fb%3Fc%3Dd%26e' safe inside a parameterWhat goes wrong with the wrong one
Encoding a value with encodeURI is the more damaging mistake, and the one that survives testing. A search term containing an ampersand passes straight through, and the server reads everything after it as a separate parameter. Your search for "salt & pepper" arrives as a search for "salt" plus an unexpected parameter named "pepper". Nothing errors; the result is simply wrong.
The opposite mistake is louder and therefore safer. Running encodeURIComponent over a whole URL escapes the slashes and the colon, producing a string no browser will treat as a link at all. That fails immediately and gets fixed immediately.
The plus sign
Percent-encoding writes a space as %20. HTML form submission uses an older convention in which a space is a plus sign. Both turn up in real query strings, sometimes in the same application, and neither decoder handles the other automatically.
The consequence is that decoding a form-encoded value with a plain URI decoder leaves literal plus signs sitting in your data, and encoding a genuine plus sign — in a phone number, or in an email address using tagged addressing — without escaping it produces a space on arrival. If a value can contain a plus, it must be encoded as %2B, and that is what encodeURIComponent does.
A plus in a query string is ambiguous by history. Encode it as %2B and the ambiguity disappears.
Double encoding
Encoding an already-encoded string escapes the percent signs themselves, so %20 becomes %2520. This usually happens when a value is encoded on the way into a template and again on the way out, or when a redirect URL is passed through two layers that each try to be helpful. The symptom is unmistakable once you know it: %25 appearing where you expected nothing, and literal percent sequences showing up in the rendered page. Decode once and check before deciding it is corrupt — often the value is fine and simply encoded twice.
What is never encoded
- The unreserved set — letters, digits, hyphen, underscore, period and tilde — is safe everywhere and left untouched by both functions.
- encodeURI additionally preserves the reserved set, including : / ? # [ ] @ ! $ & ' ( ) * + , ; =
- encodeURIComponent preserves only the unreserved set plus ! ' ( ) * , which is why it is the right choice for values.
One last note on the fragment. Everything after the hash never reaches the server; it is handled entirely by the browser. That makes it a poor place for anything sensitive and a common source of confusion when a value seems to vanish server-side. It is not being stripped — it was never sent.
Frequently asked questions
- Which one should I use to build a query string?
- encodeURIComponent, applied separately to each key and each value, then joined with the ampersands and equals signs yourself. Encoding the assembled string instead would escape the separators you just added.
- Why does my space become a plus sign instead of %20?
- Because something in the chain used HTML form encoding rather than percent-encoding. Both conventions are in active use for query strings. Decode with the same convention that produced the value, or normalise plus signs to spaces before decoding.
- Is a percent-encoded URL longer in a way that hurts SEO?
- Length itself is not a ranking factor, but unreadable URLs are worse for click-through in results and for anyone copying a link. Prefer readable slugs so the path needs no encoding at all.
Related reading
- 3 min read
camelCase, snake_case or kebab-case: Which Goes Where
Naming conventions are not preferences. Each language and format has one the tooling expects, and going against it costs more than it looks.
- 3 min read
Favicon Sizes You Actually Need
Generators offer dozens of sizes and almost nobody needs them all. Which files earn their place, which link tags matter, and why 16px decides it.
- 3 min read
How Much Can You Compress an Image Before It Shows?
The quality number is not a percentage of anything. What the artefacts look like, where they appear first, and how to find your own limit.
- 3 min read
PNG, JPEG or WebP: Which One, and Why
Three formats, one decision, and it hinges on what the image contains rather than on which format is newest. A rule and its exceptions.