URL Encoder & Decoder
Percent-encode a value or a whole URL and decode it back. Escapes are written as UTF-8 bytes per RFC 3986, so accented letters and other non-ASCII characters survive the round trip.
—
What this tool does
A URL may only contain a limited set of characters, so anything outside that set must be percent-encoded before it can travel in a link, a query string or a form field. This tool does both directions: it escapes a value or a whole URL into that safe form, and it turns an encoded string back into readable text. Because the bytes used are UTF-8, characters outside ASCII — accented letters, CJK and emoji — are encoded and decoded without corruption.
Method
There are two standard JavaScript functions and they are not interchangeable.
encodeURIComponent escapes every character that is reserved in a URL, so a value
such as a b/c?d=1 becomes a%20b%2Fc%3Fd%3D1 and is safe as a single
parameter. encodeURI leaves the separators that give a URL its structure —
: / ? # & = — unescaped and only encodes characters that are genuinely
illegal, so a complete address stays usable. Decoding uses
decodeURIComponent, falling back to decodeURI and finally to the
original text when the input is malformed. The set of characters that must be escaped, and the
%HH form of the escape, are defined by RFC 3986.
Example
| Input | Query component |
|---|---|
café | caf%C3%A9 |
a b/c?d=1 | a%20b%2Fc%3Fd%3D1 |
100% | 100%25 |
Encode the component, not the URL
This is the mistake that causes more broken links than any other. Percent-encoding protects a
component of a URL — a query value, a path segment — from the characters that give the URL
its structure. If you encode the whole URL, you also encode the ? and &
that separate the query from the path, and the server receives one long path with no query at all.
wrong: encode("https://example.com/s?q=a b")
https%3A%2F%2Fexample.com%2Fs%3Fq%3Da%20b
right: "https://example.com/s?q=" + encode("a b")
https://example.com/s?q=a%20b The rule is: build the URL from parts, and encode each part as you append it. Never encode the assembled string.
What is safe without encoding
RFC 3986 defines a set of unreserved characters that never need encoding, and encoding them anyway
is legal but noisy. This tool's encode uses the strict component rule, which escapes everything
outside A–Z a–z 0–9 - _ . ! ~ * ' ( ):
| Character | Encoded? | Why |
|---|---|---|
- _ . ~ | No | Unreserved in RFC 3986 |
! * ' ( ) | No | Sub-delimiters that are safe in a component |
space | %20 | Why the encoded form is longer |
& = ? / # | Yes | These are structural — encoding them is the whole point |
+ | %2B | Must be escaped, or a query parser reads it as a space |
% | %25 | It starts an escape; an unescaped % is invalid |
Percent-encoding is not form encoding
There are two conventions that look similar and behave differently. Percent-encoding
(RFC 3986) escapes a space as %20. Form encoding (the
application/x-www-form-urlencoded format used by HTML form submission) escapes a space as
+. Both appear in query strings, and the ambiguity is why + has to be
escaped as %2B if you mean a literal plus.
This tool uses percent-encoding, which is the correct choice for a path segment and for a value you
are building by hand. If you are reproducing an HTML form submission, the + convention
is what the server expects — and mixing the two is how a value containing a plus sign arrives as a
space.
Encoding must be reversible
Decoding is the inverse, and it has to handle three cases: a valid escape (%20 →
space), an invalid one (a lone % or a truncated %E4), and an escape that
ends mid-character. This tool leaves a malformed escape as literal text rather than throwing, because
a URL copied from somewhere may contain a percent sign that was never meant as an escape — a
100% in a path is a common example.
Note that decoding an escape produces bytes, and those bytes have to be interpreted as an encoding.
UTF-8 is the assumption everywhere, which is why caf%C3%A9 decodes to café
and not to two mojibake characters. If a URL was percent-encoded from Latin-1, decoding as UTF-8 will
produce the wrong characters — an old-system problem that still appears in integrations.
Where double-encoding comes from
If a value is passed through two layers that each percent-encode, the second layer encodes the
% of the first, and a b becomes a%2520b — the %25
being an encoded percent sign. The server decodes once and gets a%20b, which is not the
original. This is the usual cause of a parameter that “has an extra %20 in it”.
The fix is to decide which single layer owns the encoding and make the others pass the value through untouched. If you cannot change the other layers, decode one extra time — but only after confirming the double-encoding is actually there, because decoding a correctly single-encoded value corrupts it.
Unicode and the three-byte case
A non-ASCII character becomes several escapes, one per UTF-8 byte. é (U+00E9) is two
bytes, so it becomes %C3%A9; a CJK character is three bytes, so three escapes; an emoji
is four. That is why a URL for a page with non-Latin text is much longer than the text suggests, and
why a length limit measured in characters can be exceeded by an encoded URL measured in characters.
Frequently asked questions
Should a space be %20 or +?
It depends on the context. RFC 3986 percent-encoding uses %20; the HTML form encoding application/x-www-form-urlencoded uses + for a space in the query string. encodeURIComponent produces %20. In a path segment, + is a literal plus, not a space, so choose the form the receiving system expects.
What is percent-encoding?
Percent-encoding rewrites characters that are not safe in a URL as a percent sign followed by two hexadecimal digits of their UTF-8 bytes. A space becomes %20, a slash becomes %2F, and é becomes %C3%A9. It is defined in RFC 3986.
What is the difference between encoding one value and a whole URL?
Encoding a query component escapes every reserved character, so the result is safe as a single parameter value. Encoding a whole URL leaves the separators that give the URL its structure — : / ? # & = — intact and only escapes the characters that are genuinely illegal.
Why does a space sometimes become + instead of %20?
In the application/x-www-form-urlencoded format used by HTML form submissions, a space is written as +. This tool follows RFC 3986 and writes %20, which is correct inside any URL path or query string and unambiguous when decoded.
Is my text uploaded anywhere?
No. Encoding and decoding use the browser’s built-in encodeURIComponent, encodeURI and decodeURIComponent functions. The text stays on the page and no request is made.
What happens if I decode malformed input?
A lone percent sign or a truncated escape is not valid percent-encoding. The tool reports it instead of throwing, and leaves the text unchanged so nothing is silently corrupted.
Go deeper
Longer explanations of the problems this tool solves:
Sources
- RFC 3986, Uniform Resource Identifier (URI): Generic Syntax — reserved characters and percent-encoding.
Everything runs in your browser — nothing you type is uploaded.