URL Encode / Decode

Percent-encoding conversion for Chinese parameters and special characters

URL encoding, decoded: encodeURI vs encodeURIComponent and the five mistakes that bite most

Why URL encoding exists

The URL character set is deliberately tiny — RFC 3986 permits only a subset of ASCII. Any character outside that set — a space, a Chinese character, &, ?, # — must first be rewritten as percent-encoding: a % followed by two hexadecimal digits. This is the language browsers and servers use so that a URL means exactly one thing end to end.

The part people get wrong: non-ASCII characters must be UTF-8 encoded into bytes first, then each byte is percent-encoded separately. The Chinese character for "middle," 中, has UTF-8 bytes E4 B8 AD, so its encoding is %E4%B8%AD — not a single byte value. Encoding by some other charset such as GBK is the classic root cause of mojibake.

Within RFC 3986 the allowed characters split into two camps: unreserved characters (letters, digits, and a small set of marks) that never need encoding, and reserved characters that carry structural meaning and must be encoded whenever they appear outside that meaning. The percent sign itself is the escape indicator, which is exactly why encoding a percent sign produces %25 rather than leaving it untouched.

The difference between encodeURI and encodeURIComponent

This is the choice most likely to be wrong in real code, because the two functions keep different character sets unescaped:

Characters left unescapedencodeURIencodeURIComponent
letters and digitsyesyes
- _ . ! ~ * ' ( )yesyes
structural chars ; , / ? : @ & = + $ #yesno

The rule is simple:

The classic production bug: a search term of a&b passed through encodeURI stays a&b and reaches the server intact, which then reads it as two parameters — q=a and b=. The correct fix is encodeURIComponent, giving a%26b.

A useful mental model is that encodeURI assumes the string already is a URL and should remain a working URL, while encodeURIComponent assumes the string is a single value that must be dropped safely into one slot of a URL. Reaching for the wrong one is the difference between a link that works and a parameter that silently loses half its content.

Spaces: %20 or +

Both forms exist, but they belong in different places:

So a + in a path is a literal plus, not a space. Decoding /a+b/ as /a b/ is a mistake. This tool lets you pick %20 or + depending on the context and shows both results side by side so you can compare.

Five pitfalls worth committing to memory

  1. Double encoding. Encoding twice yields %2520, because the % itself becomes %25. Spotting %25 should raise an alarm that an extra layer slipped in. The test: decode once and see whether the result becomes another valid percent sequence.
  2. Encoding the value but not the key. Parameter names can contain special characters too; both sides need encoding.
  3. Forgetting to encode & and =. This is the entry point for injection-class bugs and the root of parameter confusion.
  4. Assuming the server decodes automatically. It may not. Frameworks, API gateways, and CDNs each may decode one layer or none at all. Agree on the convention before you send.
  5. Encoding # to %23 but still expecting an anchor. Once encoded, %23 is a literal character, no longer a fragment identifier.

These pitfalls share a single root cause: percent-encoding is a contract between sender and receiver, and the contract only holds when both sides agree on how many layers of encoding are in play. When a value travels through a proxy, a web framework, and a CDN, each step may add or remove one layer, and the only way to stay correct is to encode exactly once at the boundary you control and decode at the boundary the receiver controls.

Quick reference for common characters

CharacterEncodingNote
space%20standard; + in form context
&%26parameter separator, must encode in values
=%3Dkey-value separator, must encode in values
?%3Fstarts the query string
#%23starts the fragment
+%2Bleft unencoded it reads as a space
%%25the encoding prefix escapes itself
Chineseone %XX per byteUTF-8 first, then byte by byte

The tool supports one-way encoding, one-way decoding, and bidirectional conversion; you can paste either a full URL or bare text and it will handle both.

FAQ

What is the difference between encodeURI and encodeURIComponent?

The former keeps URL structural characters like / ? & = and suits a full URL; the latter escapes everything and suits parameter values. This tool uses the latter.