URL Encode / Decode

Percent-encode text for URLs and decode it back.

What URL encoding does

URLs may only contain a restricted set of ASCII characters. Anything outside that set — spaces, accented letters, emoji, and characters that have structural meaning like ?, & and # — has to be percent-encoded: replaced by a % followed by the two hex digits of each UTF-8 byte.

space -> %20   ? -> %3F   & -> %26   # -> %23
/ -> %2F   = -> %3D   + -> %2B   @ -> %40

Characters outside ASCII encode to multiple bytes. The character e-acute becomes %C3%A9 — two bytes in UTF-8 — and an emoji typically becomes four percent-escapes.

A worked example

The query coffee & cake? as a parameter value encodes to:

https://example.com/search?q=coffee%20%26%20cake%3F

Encoding the & is what prevents it from being read as a separator between parameters. Leaving it raw would split the query into q=coffee and a nonsense second parameter — the mechanism behind a whole class of parameter injection bugs.

Reserved and unreserved characters

RFC 3986 divides characters into two groups. Unreserved characters — A-Z a-z 0-9 - _ . ~ — never need encoding. Reserved characters have structural meaning and must be encoded when they appear as data rather than as delimiters.

CharacterEncodedStructural role
Space%20Terminates a URL in many parsers
?%3FStarts the query string
&%26Separates query parameters
=%3DSeparates key from value
#%23Starts the fragment
/%2FSeparates path segments
+%2BMeans space in form encoding
%%25Starts an escape sequence

The plus sign problem

There are two closely related encodings that differ in exactly one respect. In application/x-www-form-urlencoded, used by HTML form submissions, a space is encoded as +. In standard percent-encoding, a space is %20.

The consequence is that a literal plus sign in form data must be encoded as %2B, or it will be decoded as a space. This is why phone numbers in international format so often arrive with the leading + mangled into a space, and why email addresses using the user+tag@example.com convention break in badly written forms. When in doubt, encode the plus.

Encoding the whole URL versus a component

This is the most common mistake. JavaScript offers two functions:

Running encodeURI on a parameter value leaves any & inside it intact, so the value breaks out of its parameter. Running encodeURIComponent on a whole URL mangles the :// and every slash. Encode each component separately, then assemble the URL.

Double encoding

Encoding an already-encoded string escapes the percent signs themselves: %20 becomes %2520. Decoding once then yields %20 as literal text rather than a space. This produces URLs containing visible %2520 sequences and is almost always a sign that a value passed through two encoding layers — a common outcome when a proxy, framework and template each try to be helpful. The fix is to establish which layer is responsible and remove the duplicate, not to decode twice.

Internationalised domains

Domain names use a different mechanism. Non-ASCII domains are converted by Punycode into an ASCII form beginning xn--, so a domain in Greek or Devanagari script becomes something like xn--mgbh0fb.example. This is separate from percent-encoding, which applies to the path, query and fragment. Browsers display the Unicode form while resolving the Punycode one, and the gap between what is displayed and what resolves has been used for phishing — visually identical characters from different scripts can produce a lookalike domain.

Frequently asked questions

What is the difference between %20 and +?

Both can represent a space. %20 is standard percent-encoding and works anywhere in a URL. + means a space only in form-encoded data. A literal plus sign must always be written %2B, otherwise it will be read as a space.

Should I use encodeURI or encodeURIComponent?

encodeURIComponent for individual parameter values, because it escapes &, =, ? and /. encodeURI only for a complete, already-structured URL. Using the wrong one either breaks the URL structure or lets a value break out of its parameter.

Why does my URL contain %2520?

Double encoding. A string that was already percent-encoded got encoded again, turning the % of %20 into %25. Find the layer applying the second encoding rather than decoding twice to compensate.

Which characters never need encoding?

Letters, digits, and the four characters -, _, . and ~. These are the unreserved set defined in RFC 3986 and are safe anywhere in a URL.

How are emoji and non-Latin text encoded?

They are converted to UTF-8 bytes first, then each byte is percent-encoded. An accented Latin character typically becomes two escapes and an emoji four, so a short piece of non-ASCII text can expand considerably.

🔗 Related tools

Roman Numerals{ }JSON Formatter🔳QR Code Generator🆔UUID Generator🔐Base64 Encode/Decode0️⃣Binary Translator