Article · Mar 3, 2026 · 5 min read

encodeURI vs encodeURIComponent

JavaScript has two URL encoding functions: encodeURI and encodeURIComponent. They look interchangeable, they have nearly identical names, and they produce different output. Most JavaScript URL bugs trace back to using the wrong one of these two.

This article explains the difference, when to use each, and the rare cases where encodeURI is actually correct.

The short version

Use encodeURIComponent for individual parts of a URL — query parameter values, path segments, hash fragments. It encodes everything that could possibly be a special character.

Use encodeURI only when you have a complete URL where you want to preserve reserved characters (:, /, ?, &, =, #) literal. In practice, this is almost never what you want.

If you can’t articulate why you specifically need encodeURI, you want encodeURIComponent.

What each one does

encodeURIComponent: encodes more

encodeURIComponent encodes everything except:

A-Z   a-z   0-9   -   _   .   !   ~   *   '   (   )

That’s the unreserved set plus a few legacy characters. Everything else — including : / ? # [ ] @ & = + $ , — gets percent-encoded.

encodeURIComponent("https://example.com/search?q=hello world&lang=en")
// "https%3A%2F%2Fexample.com%2Fsearch%3Fq%3Dhello%20world%26lang%3Den"

encodeURI: encodes less

encodeURI leaves the structural URL characters alone in addition to the unreserved set:

; / ? : @ & = + $ , #

The rationale: these are the characters URL parsers use to split a URL into structural components. encodeURI assumes the input is a complete URL where these characters are syntax, not data.

encodeURI("https://example.com/search?q=hello world&lang=en")
// "https://example.com/search?q=hello%20world&lang=en"

Notice: the colons, slashes, ?, and & stay literal. Only the space got encoded.

When encodeURI is actually correct

The textbook case for encodeURI: you have a complete URL where:

  1. Every :, /, ?, & is structural (part of the URL syntax)
  2. You need to encode characters that violate URL syntax (spaces, non-ASCII)
  3. You haven’t pre-encoded the parts

Example: rendering a URL that came from user input where they typed accented characters:

const userTypedUrl = "https://example.com/café/menu";
const cleaned = encodeURI(userTypedUrl);
// "https://example.com/caf%C3%A9/menu"
// Now valid URL syntax

In real production code, this is rare. You usually know exactly which part of the URL is data and which is structure, so you reach for encodeURIComponent on the data parts and assemble the URL manually.

When encodeURIComponent is correct (almost always)

You have a value that’s going to be inserted into a URL. The value is data, not URL structure. Maybe it contains & or = or ? — and if those characters are interpreted as URL structure, your URL breaks.

// User search query
const q = "rock & roll";
const url = `/search?q=${encodeURIComponent(q)}`;
// "/search?q=rock%20%26%20roll"
// Server reads q="rock & roll"

// Without the encoding:
const url = `/search?q=${q}`;
// "/search?q=rock & roll"
// Server reads q="rock " and a separate parameter "roll"

The textbook mistake

// Wrong — encoding a whole URL with encodeURIComponent
const baseUrl = "https://api.example.com/search";
const url = encodeURIComponent(`${baseUrl}?q=${query}`);
// "https%3A%2F%2Fapi.example.com%2Fsearch%3Fq%3D..."
// → This is no longer a URL. It’s an encoded blob.

The fix: encode the data parts only:

const url = `${baseUrl}?q=${encodeURIComponent(query)}`;
// "https://api.example.com/search?q=encoded-query-value"

The other textbook mistake

// Wrong — using encodeURI on a value that contains a query separator
const userInput = "C&C games";
const url = `/search?q=${encodeURI(userInput)}`;
// "/search?q=C&C games"     ← encodeURI left the & alone!
// Server reads q="C", C games="" — two parameters

// Right — use encodeURIComponent for values
const url = `/search?q=${encodeURIComponent(userInput)}`;
// "/search?q=C%26C%20games"

This is the most common mistake. encodeURI looks like the “safer” encoder because of the name, but it leaves the reserved characters alone — which is exactly the problem when those characters are inside your data.

The modern alternative: URL and URLSearchParams

For 99% of cases, the right answer in modern JavaScript is to skip encodeURI / encodeURIComponent entirely and use the URL constructor:

// Building a URL
const url = new URL("https://api.example.com/search");
url.searchParams.set("q", "rock & roll");
url.searchParams.set("lang", "en");
console.log(url.toString());
// "https://api.example.com/search?q=rock+%26+roll&lang=en"

// Parsing a URL
const url = new URL("https://example.com/search?q=rock%20%26%20roll");
console.log(url.searchParams.get("q"));
// "rock & roll"

URL + URLSearchParams handle encoding automatically and correctly for each URL part. You can’t accidentally encode a structural character or forget to encode a data character.

Decision tree

You have a string to put in a URL. Which encoder?

  1. Are you building a URL with structured data? → Use new URL() + URLSearchParams. Don’t use either encode function.
  2. Are you encoding a single value (query param value, path segment, fragment)? → encodeURIComponent
  3. Do you have a complete URL with reserved characters that should stay literal? → encodeURI
  4. Are you sure? → No. Use encodeURIComponent.

Quick reference: which characters each function encodes

Character encodeURI encodeURIComponent
space%20%20
: / ? # & =literal%XX
+ ; , $ @literal%XX
! ~ * ' ( )literalliteral
é (Unicode)%C3%A9%C3%A9

For complete predictability, use encodeURIComponent on data parts and assemble URLs yourself — or better yet, use the modern URL / URLSearchParams APIs.


Found this useful? Try the URL decoder, the URL encoder, or browse all tools.

Frequently asked

Common questions.

Almost always — for any single value like a query parameter, path segment, or fragment. It escapes structural characters (? & = /) so a value can’t break the URL’s structure.

Only when you have a complete, already-structured URL and want to encode illegal characters without touching the structural ones. This is rare — in most cases the structural characters in your input are data, so encodeURIComponent is safer.

Using encodeURI on a value that contains & or = — it leaves them unencoded, so they break the query string. The reverse mistake is running encodeURIComponent on a whole URL, which encodes :// and breaks it.

URL and URLSearchParams. Build the URL from parts and let URLSearchParams encode query values once — it avoids the encodeURI/encodeURIComponent choice for most query-string work.

Sources & standards

Honest scope: MDN documents the JavaScript functions; RFC 3986 defines the underlying encoding. URLSearchParams uses form-encoding (+), which differs from encodeURIComponent (%20).

More reading

From the blog.

About this page

Written and maintained by the urlencodedecode.com team. Every technical claim on this page is verified against primary sources — the RFCs (3986, 3629, 4648, 7578), the WHATWG URL Standard, and official vendor or language documentation — rather than second-hand summaries. When a source contradicts a common assumption, we follow the source and note the discrepancy. Corrections: contactus@urlencodedecode.com.