Why there are three modes, not one#
encodeURIComponent and encodeURI are not interchangeable, and picking the wrong one either breaks a URL or fails to protect a value inside it. Component mode encodes everything except a small set of unreserved characters — letters, digits, and - _ . ! ~ * ' ( ) — which is correct for a single value going into a query parameter or path segment, since it also escapes &, =, / and ?, the characters that would otherwise be misread as URL structure.
Full URL mode does the opposite on purpose: it leaves : / ? # [ ] @ ! $ & ' ( ) * + , ; = alone, because those characters are meaningful structure in a complete URL — encoding them would turn https://example.com/a?b=1 into a mess. Use this mode only on an entire URL, never on a single parameter value.
What form-urlencoded actually is#
application/x-www-form-urlencoded is the MIME type of a standard HTML form submission, and it is close to component encoding with one specific difference: a space becomes +, not %20. This convention predates encodeURIComponent and is still what browsers send for a plain <form method="get">, and what many server frameworks expect when reading query strings and form bodies. Mixing this mode up with component encoding is a common source of a literal + showing up in decoded text instead of a space, or vice versa.
Why decoding sometimes fails#
A percent-encoded sequence is always three characters: % followed by exactly two hexadecimal digits. A stray % in text that was never actually encoded — common in URLs containing a literal percent sign, like a discount code — breaks decoding outright, since the decoder cannot tell a real escape sequence from an unrelated % followed by ordinary text. This tool reports that failure explicitly instead of silently returning something wrong.