Xerobit

URL Encoder / Decoder

Percent-encode URLs and query-string values, or decode them back. Four variants cover every real-world case: query values, full URLs, strict RFC 3986, and application/x-www-form-urlencoded form data.

Ready. Paste text or a percent-encoded URL.
encodeURIComponent (default) = safe for query values (encodes / : ? # & = +). encodeURI = safe for whole URLs (leaves / : ? # & = alone). RFC 3986 = strictest, also encodes ! * ' ( ). form = + for space instead of %20.

How to URL encode: step by step

  1. Pick a mode: Encode or Decode.
  2. Pick a variant that matches your target: query value (encodeURIComponent), full URL (encodeURI), RFC 3986 strict, or form data (application/x-www-form-urlencoded).
  3. Paste your text into the input box. The result appears automatically after 150 ms.
  4. Click Copy to copy the output to your clipboard.
  5. Use Swap to flip the output back into the input and reverse the mode: handy for round-trip checks to confirm the original string is recovered.

URL encoder: copy and paste examples

Paste any of the inputs below into the encoder and select the matching variant to see the output. These cover the most common real-world encoding scenarios.

InputVariantEncoded output
hello worldencodeURIComponenthello%20world
name=Ada&role=adminencodeURIComponentname%3DAda%26role%3Dadmin
https://example.com/path?q=hello worldencodeURIhttps://example.com/path?q=hello%20world
café au laitencodeURIComponentcaf%C3%A9%20au%20lait
search termform-urlencodedsearch+term
C++encodeURIComponentC%2B%2B
price: $20 & taxencodeURIComponentprice%3A%20%2420%20%26%20tax

To decode, paste the percent-encoded string (e.g. hello%20world), switch to Decode mode, and the original text appears.

Which variant should I use?

Picking the wrong variant causes half the "mystery" URL bugs in production. Here's the decision guide:

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.

RFC 3986 defines 66 "unreserved" characters that are never encoded: A-Z, a-z, 0-9, -, _, ., and ~. Everything else is fair game depending on context. For the full specification, see the percent-encoding RFC 3986 explainer.

When to use URL encoding

URL encoding is required any time user-controlled text crosses a URL boundary:

  • Search queries: Encode the search term before appending it to ?q=. Without encoding, a query like rock & roll breaks the parameter structure.
  • User-generated slugs: File names, usernames, or titles with spaces or special characters must be encoded in path segments.
  • OAuth and API authentication: Many OAuth 1.0a signature base strings require RFC 3986 strict encoding of the entire request URL.
  • Redirect targets: When a URL is passed as a parameter to a redirect endpoint (e.g., ?next=/dashboard), the value must be encoded so its slashes aren't parsed as the outer URL's path.
  • Form submissions: HTML forms use application/x-www-form-urlencoded by default: the browser handles it, but when building form bodies in code you need to encode manually.
  • International and emoji content: Any non-ASCII text in URLs: language content, emoji in UTM parameters, CJK characters in file paths, must be percent-encoded as UTF-8 bytes.
  • Webhook payloads and callback URLs: When passing a callback URL as a query parameter, always encodeURIComponent the full callback URL string.

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. See the full post: double URL encoding, causes and fixes.

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.

For a complete field guide to all seven common URL encoding bugs, see URL encoding bugs that break your API.

URL encoding by language

The encoder above handles ad-hoc encoding, but here are the idiomatic approaches in code:

  • JavaScript: Use encodeURIComponent(value) for values; new URLSearchParams(obj) for query strings. See URL encoding in JavaScript.
  • Python: Use urllib.parse.quote(value) for path segments; urllib.parse.urlencode(dict) for query strings. See URL encoding in Python.
  • curl: Pass --data-urlencode 'key=value' for POST; use -G --data-urlencode for GET query params. See URL encoding in curl.

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 the same as + for a space?

Only in specific contexts. In query strings, %20 = space and + = literal plus. In form-encoded bodies, + = space and %2B = literal plus. Match your encoder to your consumer, never assume.

Does this tool handle non-ASCII and emoji correctly?

Yes. The tool uses JavaScript's native encodeURIComponent / decodeURIComponent, which always operate on UTF-8 bytes. You can paste CJK characters, Arabic, 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. Usual cause: an unescaped % that isn't followed by two hex digits (e.g., a literal % sign in a URL). Fix it by encoding the bare % as %25 before passing it to a decoder.

What is the difference between URL encoding and Base64?

URL encoding (%XX) makes individual characters safe for use inside a URL. Base64 encoding converts arbitrary binary data into a printable ASCII string, it's used for embedding data in HTML, JSON, or email headers, not for URL safety. They solve different problems; sometimes both are used together (Base64-encode binary, then URL-encode the result for a query param).

Part of the Encoding & Crypto pillar

This tool is part of the Encoding & Crypto collection, Base64, URL, JWT, hashes, UUID, QR codes, and password generation, all running client-side with no data sent to a server.

Written and maintained by Mian Ali Khalid. Last updated 2026-05-12.