How to use
- Choose Encode or Decode.
- For encoding, say what the text is under Encode as: a single value (one query parameter or path segment), a whole URL, or a form field.
- For decoding, leave Treat "+" as a space on for query strings and form data; turn it off for a path where
+is a literal plus. - Copy to clipboard, or ⇄ Swap to run the result back the other way.
Why URLs need percent-encoding
A URL can only safely contain a limited set of characters: letters, digits, and a handful of punctuation marks that have no special meaning in that position. Everything else (spaces, ampersands inside a value, non-English characters, slashes inside a value rather than as a path separator) has to be percent-encoded: replaced with % followed by its byte value in hex, as laid out in RFC 3986 §2.1. A space becomes %20, an ampersand becomes %26, and a character outside ASCII becomes one %XX group per UTF-8 byte.
Get this wrong and a URL either breaks outright or, worse, silently does the wrong thing. An unencoded &inside a query value looks like the start of the next parameter, quietly truncating or corrupting the one before it.
Example
Encoding hello world & more/less? as a single value gives:
hello%20world%20%26%20more%2Fless%3FEvery character outside letters, digits and -_.~ is escaped, including the slash and question mark, since as a value they carry no special meaning.
Component vs. full-URL encoding
The common mistake is running an entire URL through component-style encoding, which escapes the very characters (:, /, ?, &, =) that make it a URL in the first place. The rule of thumb: encode a value that will be placed inside a URL with the component option; only use the full-URL option on something that is already a complete, structurally valid URL and only needs its non-ASCII or space characters escaped. https://x.y/p q?a=b c&d=é#h in whole-URL mode becomes:
https://x.y/p%20q?a=b%20c&d=%C3%A9#hOptions explained
- Encode as: A single value (encodeURIComponent) escapes everything except letters, digits and
- _ . ! ~ * ' ( ). Use it for one query value or one path segment. - A whole URL, keep :/?#&= intact (encodeURI) leaves the characters that give a URL its structure alone and escapes only spaces, non-ASCII and a few others, as in the example above.
- A form field (spaces become "+") is single-value encoding with
%20replaced by+, matchingapplication/x-www-form-urlencoded. A literal+in the input becomes%2B, so it stays unambiguous:a b+c→a+b%2Bc. - Treat "+" as a space (decode only): on,
a+b%20c→a b c; off,a+b c. Turn it off for path segments and for Base64 values, where+is data. - ⇄ Swap moves the output into the input and flips the direction. Load sample inserts a URL with a space in its query string in Encode mode, or an already-encoded value in Decode mode.
Edge cases and common errors
- Already-encoded text gets encoded again.
a%20b→a%2520b. Decode first if you are unsure where a value came from;%2520decodes back to%20one layer at a time. - Whole-URL mode does not protect values. It leaves
?,#and&alone even inside a query value, sohttps://x.y/?q=a&bstays ambiguous. Encode the value on its own with single-value mode and build the URL around it. - A stray
%:100%or a sequence cut short like%E0%A4%Afails with “Malformed percent-encoding: every "%" must be followed by exactly two hex digits”. Encode a literal percent sign as%25. - Valid hex, invalid text:
%FFis well-formed but is not UTF-8, so it fails with “The percent-encoded bytes are not valid UTF-8 text, so they cannot be shown as characters”. Latin-1 URLs from older systems hit this; decode them with a tool that lets you pick the charset. - Non-ASCII becomes UTF-8 bytes:
é→%C3%A9, and an emoji becomes four%XXgroups. Newlines are encoded as%0A. - Half an emoji: a lone surrogate left behind by a truncated paste is not a valid character. The browser's own
encodeURIComponentthrows on it; this tool substitutes the replacement character instead, soa+ a lone surrogate +bencodes asa%EF%BF%BDb, the same as the Base64 tool does. ! * ' ( )are left unescaped byencodeURIComponenteven though RFC 3986 lists them as reserved sub-delimiters. Most servers accept either form; if a strict API rejects them, replace by hand:!→%21,'→%27,(→%28,)→%29,*→%2A.- Base64 in a query string needs encoding too, because
+and/are not safe. Alternatively, use the URL-safe Base64 alphabet and skip this step.
Do the same thing in code
JavaScript
encodeURIComponent("hello world & more"); // "hello%20world%20%26%20more"
encodeURI("https://x.y/p q?a=b c"); // "https://x.y/p%20q?a=b%20c"
decodeURIComponent("hello%20world"); // "hello world"
new URLSearchParams({ q: "a b+c" }).toString(); // "q=a+b%2Bc" (form encoding)Python
from urllib.parse import quote, unquote, quote_plus
quote("hello world & more") # 'hello%20world%20%26%20more'
quote_plus("hello world") # 'hello+world'
unquote("hello%20world") # 'hello world'