How to use this URL Encoder Decoder
Paste your text or encoded URL content into the input box, then choose whether you want to
encode it or decode it. The result appears instantly in the output area.
- Paste readable text or encoded URL text into the input box.
- Click Encode to create percent-encoded output.
- Click Decode to turn encoded text back into readable text.
- Copy the output if you need to use it elsewhere.
Example conversion
Input: hello world?x=1&y=2
Encoded: hello%20world%3Fx%3D1%26y%3D2
Common use cases
- Query string building
- Redirect URLs
- API request parameters
- Path-safe values
- Encoded link debugging
Percent-encoding works on bytes, not characters
The mechanism itself is simple: each unsafe byte is replaced by a % followed
by the two hexadecimal digits of that byte's value. A space is byte 0x20, so
it becomes %20; a question mark is 0x3F, so it becomes
%3F. The important word is byte. Percent-encoding does not
operate on characters — it operates on the bytes a character produces once the text has
been turned into an encoding, which on the modern web is always UTF-8.
That distinction bites the moment you leave plain ASCII. An ASCII letter is a single byte
and encodes to a single escape. But é is code point
U+00E9, which UTF-8 stores as the two bytes 0xC3 0xA9, so it
encodes to %C3%A9 — two escapes for one character. An emoji
such as 😀 (U+1F600) is four UTF-8 bytes and becomes
%F0%9F%98%80, four escapes for one character. Because of this, counting
% sequences tells you nothing about how many characters a string holds, and a
decoder that receives a truncated sequence like a lone %C3 will reject it as
invalid UTF-8 rather than guess.
encodeURI vs encodeURIComponent: the bug behind most broken URLs
JavaScript ships two encoders and picking the wrong one is the single most common
URL-encoding mistake. encodeURI() is meant for a whole URL, so it
deliberately leaves the reserved delimiters — : / ? # & = and friends —
untouched, because encoding them would break the URL's structure.
encodeURIComponent() is meant for a single piece, one query value or
one path segment, so it does encode those delimiters.
The classic production bug: taking a query-parameter value that contains an
& or = and running it through encodeURI() (or
nothing at all). Those characters pass straight through, the receiving server reads them as
structure rather than data, and a value like name=a&admin=true silently
injects an extra parameter. The rule is mechanical:
use encodeURIComponent() on every individual name and value, and reserve
encodeURI() for a complete URL you assembled yourself. Better still, let the
URL and URLSearchParams APIs build the query string — they apply
the correct encoding per component for you.
Reserved vs unreserved: where the real difficulty lives
RFC 3986 splits characters into two groups. The unreserved set —
A–Z, a–z, 0–9 and the four marks
- _ . ~ — never carries structural
meaning and never needs encoding anywhere in a URL. The reserved set —
: / ? # [ ] @ ! $ & ' ( ) * + , ; = — is the set of delimiters that give a
URL its shape.
For a reserved character there is no fixed answer to "should I encode this?" It depends
entirely on whether you mean it as a delimiter or as literal data, and that ambiguity is
the whole difficulty of URL encoding. A / that separates path segments must
stay raw; a / that is part of a value — say the string 2024/01
used as a single path segment — must become %2F, or it splits into two
segments and routes to the wrong place. The character is identical; only your intent
differs, and only encoding records that intent.
Is a space %20 or +? It depends who encoded it
Both appear in the wild, and they come from two different conventions. The
+-means-space rule belongs specifically to
application/x-www-form-urlencoded — the format of HTML form submissions and
traditional query strings — not to URLs in general. In a generic URL a literal
+ is a plus sign, and a space is %20.
encodeURIComponent() follows the generic rule and always produces
%20, never +.
Decode a string with the wrong convention and you corrupt data quietly. Feed a
form-encoded a+b to a plain URL decoder and you get a+b back
instead of a b; encode a value that genuinely contains a + and
hand it to a form decoder, and your plus sign turns into a space. Neither error throws — the
output just looks slightly wrong — so you have to know which convention produced the string
before you decode it.
Double-encoding, %2520, and one quirk to know
If a value passes through two layers that both encode it, the second pass re-encodes the
% signs the first pass introduced. Because % is itself
0x25, it becomes %25, and so %20 turns into
%2520. When users report seeing literal %20 or %2520
in a rendered page, a URL, or a downloaded filename, that is the fingerprint of
double-encoding. The fix is to find and remove the extra layer, then decode exactly as many
times as the value was encoded — no more.
One last quirk worth knowing: encodeURIComponent() does not
encode ! ' ( ) *, even
though RFC 3986 lists them as reserved sub-delimiters. For most links this is harmless, but
where strict compliance matters — OAuth 1.0 signature base strings are the usual example —
you must post-process them yourself, replacing those five with %21,
%27, %28, %29, and %2A.
Frequently Asked Questions
Should I use encodeURI or encodeURIComponent?
Use encodeURIComponent() for a single piece of a URL — one query value or
one path segment — because it encodes the reserved delimiters
(& = / ? #) that would otherwise break the structure. Use
encodeURI() only on a complete URL you built yourself, since it leaves
those delimiters intact so the URL keeps working. When in doubt, encode components with
encodeURIComponent() or build the query with URLSearchParams.
Why did my query parameter break when the value contained an &?
Because the value was encoded with the wrong function — encodeURI() or
nothing — which leaves & and = untouched. The server then
reads that & as a separator and treats the rest of your value as extra
parameters. Encode each value with encodeURIComponent(), which turns
& into %26 and = into %3D so
they stay part of the data.
Is a space encoded as %20 or +?
In a URL a space is %20, and that is what
encodeURIComponent() produces. The + form belongs only to
application/x-www-form-urlencoded data — HTML form bodies and traditional
query strings. Decode a string with the wrong convention and a+b stays
a+b instead of becoming a b, so match the decoder to whoever
encoded it.
Which characters never need URL encoding?
The unreserved set from RFC 3986: A–Z, a–z,
0–9, and the four marks - _ .
~. These are safe in any part of a URL. Everything in the reserved set
(: / ? # & = and others) is a delimiter, and whether it needs encoding
depends on whether you mean it as structure or as literal data.
Why do I see %2520 in my URL?
That is double-encoding. A value was encoded twice, so the % of an
existing %20 got re-encoded to %25, giving
%2520. It usually means two layers of your stack both apply encoding. Find
and remove the extra layer, then decode the value exactly as many times as it was
encoded.
How are accented letters and emoji encoded?
One UTF-8 byte at a time. Percent-encoding runs on bytes, so é
(UTF-8 0xC3 0xA9) becomes %C3%A9 — two escapes for one
character — and an emoji, which is four UTF-8 bytes, becomes four escapes such as
%F0%9F%98%80. The number of % sequences therefore does not
match the number of characters.