How to use the URL encoder / decoder
- Pick a mode — Encode or Decode.
- Pick a variant that matches your target: query value, full URL, RFC 3986 strict, or form data.
- Paste into the left textbox. Processing runs automatically after 150ms.
- Click Copy to copy the output. Swap moves the output back into the input and flips the mode for round-trip checks.
Which variant should I use?
This is the question that trips up 90% of developers — and picking the wrong variant causes half the "mystery" URL bugs in production.
encodeURIComponent (default) — for a single value
Use this when you're encoding a value that will be placed inside a URL — a query-string value,
a path segment, or a header. It encodes every character that has special meaning in URLs (/ : ? # & = +),
which is exactly what you want for a value. This is the right default almost always.
const params = new URLSearchParams();
params.set('q', userInput);
fetch('/search?' + params); // URLSearchParams does encodeURIComponent for you
encodeURI — for an entire URL
Use this when you have a full URL and want to escape only the truly illegal characters
(spaces, non-ASCII) while leaving the URL structure (/, ?, #,
&, =) intact. Rare — most of the time you're building URLs from parts, not
escaping whole URLs. If you're tempted to use this to encode a query value, you're almost certainly wrong.
RFC 3986 strict
Stricter than encodeURIComponent. Also encodes !, *,
', (, ) — characters RFC 3986 marks as "sub-delims" that
some parsers treat as special. Use this when you need maximum compatibility with strict URI parsers
(some older OAuth flows, some XML-based APIs).
application/x-www-form-urlencoded
Used in HTML <form> submissions with method="POST" and the default
enctype. The one meaningful difference from encodeURIComponent: spaces become
+ instead of %20. If you're building form bodies manually (no
URLSearchParams), use this. In decoder mode, this option treats + as space.
What does percent-encoding actually do?
Every character becomes %XX where XX is the hex value of its UTF-8 byte(s).
ASCII characters below 128 take one byte (e.g., space = %20). Non-ASCII characters take
2–4 bytes (e.g., é = %C3%A9, the UTF-8 bytes of U+00E9).
The set of characters that get encoded depends on the variant — that's all the variants do differently. The encoding math is identical; the "character allowlist" is what changes.
Common URL encoding bugs
Double-encoding
The most common bug. Something encodes once, then a middleware or framework encodes the output again.
Result: %20 becomes %2520, and the %20 decoded once says "20"
instead of a space. If you see %25 pairs mysteriously appearing, you're double-encoding.
Using encodeURI for a query value
encodeURI("a&b=c") returns a&b=c unchanged — because &
and = are "valid" in a URL. Your server then parses two query params (a and
b) instead of one. Use encodeURIComponent for values, always.
Plus becomes space (or doesn't)
In the query string of a URL, + is a literal plus sign. But in an
application/x-www-form-urlencoded body, + is a space. Servers treat them
differently depending on whether they're parsing the URL or the body. This is why you see PHP's
urldecode (form style) vs rawurldecode (URL style).
Forgetting to encode the fragment
Everything after # in a URL is the fragment. Browsers encode fragments differently from
query strings — ? and & are allowed unescaped, but #
itself must be encoded. Get this wrong and deep-linked SPAs with # in state break.
Frequently asked questions
Why are some characters never encoded?
RFC 3986 defines "unreserved" characters that always stay literal: A-Z, a-z,
0-9, -, _, ., and ~. These are safe in
every URL context, so no encoder touches them. Everything else depends on context (and the variant).
Is %20 and + the same thing?
Yes and no. In query strings, %20 = space and + = literal plus. In form bodies,
+ = space and %2B = literal plus. Don't assume — match your encoder to your
consumer.
Does this tool handle non-ASCII correctly?
Yes. The tool uses JavaScript's native encodeURIComponent / decodeURIComponent,
which always use UTF-8. You can paste CJK, emoji, or any Unicode and the encoded output is valid percent-encoded UTF-8.
Why did my decode fail with "URI malformed"?
You have an invalid escape sequence somewhere. Usual cause: an unescaped % character that
isn't followed by two hex digits. Escape literal % as %25.
Is there a difference in what servers accept?
Almost none for the ASCII part — servers respect RFC 3986. The edge cases are mostly in how they parse
form bodies vs query strings, and in how they handle +. Test both sides of your boundary.
Related tools
- JSON Formatter — Format, validate, and beautify JSON online. 100% client-side — your data never leaves your browser.
- Base64 Encoder / Decoder — Encode and decode Base64 strings and files. Client-side, safe for sensitive data.
- JWT Decoder — Decode and inspect JSON Web Tokens. Local-only — tokens never leave your browser.
- Hash Generator — Generate MD5, SHA-1, SHA-256, and SHA-512 hashes client-side.
Further reading
Pillar
Part of Encoding & Crypto — Base64, URL, JWT, hashes, UUID, QR, password.
Written and maintained by Mian Ali Khalid. Last updated 2026-04-25.