toolhq.io

All posts
5 min readby Jameel Haider

When to use encodeURIComponent instead of encodeURI

JavaScript gives you two built-in URL encoders, encodeURI and encodeURIComponent, and choosing the wrong one produces broken links or corrupted parameters. The names sound almost interchangeable, but they are built for opposite jobs. One encodes a whole URL, the other encodes a single piece that will be dropped into a URL.

The core distinction

encodeURI assumes you are handing it a complete, already-structured URL and you want to make it safe to transmit without destroying its structure. So it deliberately leaves the characters that give a URL its shape untouched: the scheme separator, slashes, the query marker, the fragment hash, and so on.

encodeURIComponent assumes you are handing it one value, a path segment or a query parameter value, that must survive intact even if it happens to contain those same structural characters. So it encodes them too.

The result is that encodeURIComponent escapes a larger set of characters.

CharacterencodeURIencodeURIComponent
/ ? : @ & = + $ , #left aloneescaped
A-Z a-z 0-9left aloneleft alone
- _ . ! ~ * ' ( )left aloneleft alone
space%20%20

Both functions leave the unreserved set and the handful of marks in the last row untouched, and both turn a space into %20. The difference is entirely in that first row: the reserved characters that structure a URL.

Which to use

Use encodeURIComponent for any value you are inserting into a URL:

const q = 'tom & jerry';
const url = 'https://example.com/search?q=' + encodeURIComponent(q);
// https://example.com/search?q=tom%20%26%20jerry

The ampersand in the value becomes %26, so it cannot be mistaken for a parameter separator. This is almost always what you want when building URLs programmatically.

Use encodeURI only when you have a whole URL string and simply want to clean up illegal characters like spaces, without altering its anatomy:

encodeURI('https://example.com/my path?x=1');
// https://example.com/my%20path?x=1

Here the ://, /, ?, and = are preserved because they are doing their structural jobs.

The classic bug

The most common mistake is using encodeURI to encode a query parameter value. Watch what happens:

const q = 'a=1&b=2';
'https://example.com/?q=' + encodeURI(q);
// https://example.com/?q=a=1&b=2   <-- broken

encodeURI left the = and & alone because it thinks they are URL structure. The server now sees three parameters (q=a, 1, b=2) instead of one parameter whose value is the literal string a=1&b=2. Using encodeURIComponent produces q=a%3D1%26b%3D2, which decodes back to exactly what you sent.

Do not double-encode

The other frequent error is encoding something twice. If a value has already been encoded, running encodeURIComponent again turns every % into %25, so %20 becomes %2520. The reader then decodes once and gets %20 as literal text rather than a space. Encode exactly once, at the moment you assemble the URL, and decode exactly once when you read it. If you are stitching together a value that came from location.search, decode it first or keep it in its decoded form until the final assembly.

A quick way to check your output is to encode a tricky value, then decode it and confirm you get the original back. Paste a value with ampersands and equals signs into the URL Encoder / Decoder and compare the two functions side by side.