Both encodeURI and encodeURIComponent turn text into a URL-safe form, but they escape different characters, and picking the wrong one is one of the most common causes of broken links and corrupted query parameters in JavaScript. Here is the difference, when to use each, and how to never get it wrong again.
The short answer
Use encodeURIComponent for a single piece of data you are inserting into a URL, such as one query parameter value or one path segment. Use encodeURI only when you are encoding a complete, already-assembled URL and need its structure left intact. In day-to-day code, you want encodeURIComponent the large majority of the time.
encodeURIComponent. Cleaning up a whole URL you already built means encodeURI.
Why two functions exist at all
A URL is made of structural characters that have specific jobs. The ? starts the query string, & separates parameters, = ties a key to its value, / separates path segments, and # begins the fragment. These characters mean something when they appear in the right place.
The problem is that the same characters might also appear inside your data. If a user’s search term contains an ampersand, and you drop it raw into a URL, the server cannot tell your ampersand apart from the one separating parameters. The two functions exist because sometimes you want those structural characters preserved (you are encoding a whole URL) and sometimes you want them escaped (you are encoding a value that must not disturb the URL’s structure).
The exact difference
encodeURI assumes you are handing it a complete URL, so it deliberately leaves the structural characters alone. It will not touch : / ? & = # + and a few others, because in a full URL those are doing their job.
encodeURIComponent assumes you are handing it a single component that will be slotted into a URL, so it escapes those structural characters too, because in that context they are data, not structure.
| Character | encodeURI | encodeURIComponent |
|---|---|---|
& | left as is | %26 |
= | left as is | %3D |
? | left as is | %3F |
/ | left as is | %2F |
# | left as is | %23 |
| space | %20 | %20 |
So both encode a space, but only encodeURIComponent escapes the characters that would otherwise break a query parameter. That single column of differences is the entire reason people get bitten.
A concrete example
Imagine a search term that itself contains URL-special characters: tom & jerry?. Watch what each function does when you try to put it into a query string.
const term = "tom & jerry?"; // WRONG: encodeURI leaves & and ? intact "https://site.com/search?q=" + encodeURI(term); // => https://site.com/search?q=tom%20&%20jerry? // The & looks like a new parameter. The ? looks like a second query. // The server misreads the whole thing. // RIGHT: encodeURIComponent escapes them "https://site.com/search?q=" + encodeURIComponent(term); // => https://site.com/search?q=tom%20%26%20jerry%3F // The entire term is now one safe, intact value.
With encodeURI, the unescaped ampersand makes the server think a new parameter has begun, and the question mark looks like a second query string. The value is silently corrupted. With encodeURIComponent, every special character in the term becomes a percent sequence, so it survives as a single intact value. You can paste either result into the URL encoder / decoder to decode it back and confirm what the server would actually receive.
The most common real-world mistake
The classic bug is building a query string by encoding the whole thing at once with encodeURI:
// BUG: a value containing & will break this
const url = encodeURI(`https://site.com/api?name=${name}&city=${city}`);
If name contains an ampersand, encodeURI leaves it alone and your parameters collide. The fix is to encode each value individually as a component, then assemble:
// CORRECT: encode each value as a component
const url = `https://site.com/api?name=${encodeURIComponent(name)}&city=${encodeURIComponent(city)}`;
Better still, modern JavaScript has URLSearchParams, which encodes values correctly for you and removes the chance of getting it wrong by hand:
const params = new URLSearchParams({ name, city });
const url = `https://site.com/api?${params.toString()}`;
What about decoding?
The same split applies in reverse. decodeURIComponent decodes a single value, and decodeURI decodes a whole URL while preserving structure. If you are pulling one parameter value out of a query string, use decodeURIComponent. A lone % that is not followed by two valid hex digits will throw an error in either, which usually means a literal percent sign in the data was not encoded as %25.
%20 and other sequences back to readable text. It runs entirely in your browser, so nothing you paste is uploaded.
Frequently asked questions
Should I use encodeURI or encodeURIComponent?
Use encodeURIComponent for individual values like query parameters or path segments, which is what you need most of the time. Use encodeURI only to encode a complete URL whose structural characters should be preserved.
Why does encodeURI leave the ampersand alone?
Because encodeURI assumes it is being given a whole URL, where the ampersand is a structural character that separates parameters. It deliberately preserves it. That is exactly why you should not use encodeURI on a value that itself contains an ampersand.
Does encodeURIComponent handle non-English characters?
Yes. Both functions convert characters to their UTF-8 bytes and percent-encode each byte, so accented letters, non-Latin scripts, and emoji all encode correctly.
What is the easiest way to build a safe query string?
Use the built-in URLSearchParams object, which encodes each value correctly for you and removes the risk of choosing the wrong function by hand.

