Guide

How URL percent-encoding works

Learn which characters to encode in a URL component, how UTF-8 becomes percent triplets, and why + does not always mean space.

by Tools in a Tab · Published on · Updated

Short answer

Percent-encoding represents one byte as % followed by two hexadecimal digits. It lets data appear inside a URI component without being confused with structural delimiters.

text:      café & tea
component: caf%C3%A9%20%26%20tea

é first becomes UTF-8 bytes C3 A9, written as %C3%A9. The space becomes %20, while & becomes %26 so it is not read as a parameter separator.

Unreserved and reserved characters

RFC 3986 defines letters, digits, -, ., _, and ~ as unreserved. Reserved characters can have structural roles, including :, /, ?, #, [, ], and @, or separate subcomponents, such as & and =.

Do not encode an entire URL as if it were one value: that would also encode /, ?, and other delimiters needed by the structure. Encode the individual name or value you insert.

To reproduce the example, select URL component in the URL encoder. The tool also has Complete URL or path mode, which preserves structural delimiters, and Form/query value mode, which writes spaces as + and a literal plus as %2B. Choose the mode for the layer you are editing; complete-URL mode cannot tell which & or ? characters you intended as data inside a value.

The + case

In application/x-www-form-urlencoded, a space is commonly represented as +. In general URI percent-encoding, a space is %20, and a literal + remains + unless the form-decoding layer applies its own rule. Know which decoder receives the value.

Common mistakes

  • Encoding %C3%A9 a second time as %25C3%25A9.
  • Decoding before separating components and turning data into structure.
  • Placing standard Base64 in a URL without handling +, /, and =.
  • Accepting incomplete % sequences or bytes that are not valid UTF-8.

When JavaScript throws URIError: URI malformed, follow the strict diagnosis for incomplete escapes, UTF-8, and lone surrogates instead of replacing every percent sign or decoding repeatedly.

Keep URL construction, component encoding, and form serialization as separate layers. They are related, but not interchangeable.