Short Answer
for data only intended to be parsed by JavaScript, use escape()
, for anything else, use encodeURIComponent()
encodeURI and encodeURIComponent
encodeURI
and encodeURIComponent
do the same thing: they URL-Encode a string. There is an important difference, though: encodeURI
respects the structure of an URI, while encodeURIComponent
does not. In most cases, you won't notice the difference, but when the argument you pass is a valid URI, encodeURI
won't encode some characters of it, while encodeURIComponent
ignores the URI structure of the passed argument, and encodes all characters which are invalid/have special meaning in an URI:
console.log(encodeURIComponent("Some Example Text"),encodeURI("Some Example Text"));//==>Some%20Example%20Text Some%20Example%20Text
console.log(encodeURIComponent("https://example.com/äöü?param1=content"),encodeURI("https://example.com/äöü?param1=content"));
In the example above, you can clearly see how encodeURIComponent
behaves the same way as encodeURI
when no URI structure is given, but when it is given, encodeURI
skips characters relevant to the URI's structure, where encodeURIComponent
ignores these. In most cases, encodeURIComponent is what you want. I cannot think of any use cases where encodeURI is the better choice, if you have user data, it is better to do:
var url="https://example.com/upload?input="+encodeURIComponent(user_input);
instead of:
var url=encodeURI("https://example.com/upload?input="+user_input)
because a user might insert URI-corrupting data (accidentally or maliciously (even though preventing attacks on client-side is a bad idea anyways) or because a malicious actor told him to) like:
upload_data?second_parameter=unintended_content
which the would be encoded properly in example 1, but generate errorneous or even malicious URI's in example 2.
BOTH METHODS THROW AN ERROR IF A LONE SURROGATE (0xD800-0xDFFFF) IS IN THE PASSED STRING
escape
Even though escape
might look like it URI-Encodes a string, it actually translates it into a javascript specific format. When only characters in range (0x00-0x7F
) are encoded, it behaves the same as encodeURIComponent
(not encodeURI, because it ignores the URI structure just like encodeURIComponent does), except for 3 special characters, which it does not encode, even though they might have a special meaning in the URI (@+/
). Behaviour differs for code points above 0x7F:
escape
translates it into %uXXXX
when the code point is above 0xFF, for code points in range 0x80-0xFF, escape
translates it into %XX
encodeURIComponent
URL-encodes it regularly, and throws an URIError
for lone surrogates, which is the reason why escape()
is the more robust method.
//0x00-0x7F
console.log(escape("Some Example Text"),encodeURIComponent("Some Example Text")); //==> Some%20Example%20Text Some%20Example%20Text
//Special Characters
console.log(escape("@+/"),encodeURIComponent("@+/"))//==>@+/ %40%2B%2F
//Above 0x7F
console.log(escape(String.fromCodePoint(0x1234)),encodeURIComponent(String.fromCodePoint(0x1234)));//==> %u1234 %E1%88%B4
//2 Valid Surrogates
console.log(escape("😂"),encodeURIComponent("😂"));//==> %uD83D%uDE02 %F0%9F%98%82
//Lone Surrogate(0xD800-0xDFFF)
console.log(escape(String.fromCodePoint(0xD800)))//==> %uD800
encodeURIComponent(String.fromCodePoint(0xD800))//URIError
It is also noteworthy that escape is deprecated, but it is supported by all major browsers (even IE, although I don't think anyone uses it anymore) , and there is no reason why support might be dropped in the future.
When to Use encodeURIComponent and when to use escape?
For data only intended to be parsed by JavaScript (for example in the hash of an URI), use escape
, for anything else, use encodeURIComponent
(and almost never use encodeURI
)
About decoding
no matter which of the 2 real options you choose, you need to use the proper decoding method:
encodeURIComponent ==> decodeURIComponent
escape ==> unescape
If you don't know how the string was encoded, use the following function to detect it automatically (unreliable/errorneous when characters in range 0x80-0xFF are encoded with escape, and no characters >0xFF are encoded along with it, reliable in most other cases):
decode=function(text){return (text.includes("%u")?unescape(text):decodeURIComponent(text))}
encodeURIComponent("var1=value1&var2=value2")
is not the typical use case. That example will encode the=
and&
, which is probably not what was intended!encodeURIComponent
is typically applied separately to just the value in each key value pair (the part after each=
). – Placemanvar params = encodeURIComponent(key) + '=' + encodeURIComponent(value);
- Maybe someone else knows a better way. – Thoughtful