Skip to content
Buy me a coffee
Encoders / Cryptography

URL Encoder / Decoder

Encodes or decodes a string so that it conforms to the URL specification (RFC 3986 / RFC 1738). All reserved characters are percent-encoded.

Controls which characters are left untouched. Decoding always accepts any %XX sequence.
Non-ASCII characters are converted to bytes in this charset before being percent-encoded.
Ctrl + Enter

URL Encoding Explained

Why do URLs need to be encoded?

A URL (Uniform Resource Locator) can only be transmitted over the Internet using the US-ASCII character set, and even inside that set a number of characters have a special meaning: ? starts the query string, & separates parameters, = separates a name from its value, # introduces a fragment, / separates path segments, and so on. RFC 3986 (which replaced RFC 1738) therefore defines a small set of unreserved characters that may appear literally anywhere, a set of reserved characters that carry meaning, and a mechanism called percent-encoding for everything else. A URL that contains a space, an accented letter, a Chinese ideogram or a stray ampersand in a parameter value must be encoded before it is sent, otherwise servers and browsers will misinterpret it (or reject it).

How does percent-encoding work?

Each byte that is not allowed is replaced by a percent sign followed by the two hexadecimal digits of the byte value: % + XX. Characters outside US-ASCII are first converted to a sequence of bytes using a character encoding, almost always UTF-8 (as recommended by RFC 3986 and mandated by the WHATWG URL standard). The letter é is C3 A9 in UTF-8 and therefore becomes %C3%A9; in ISO-8859-1 it would be the single byte E9, hence %E9. This is why the character set matters when you decode a URL produced by an old application.

A space is a special case: RFC 3986 encodes it as %20, while HTML forms submitted as application/x-www-form-urlencoded historically replace it by a plus sign +. Because of this, a literal plus sign inside a form value must itself be encoded as %2B.

Reserved and unreserved characters

ClassCharactersTreatment
UnreservedA–Z a–z 0–9 - _ . ~Never need to be encoded (encoding them is allowed but pointless).
Reserved — general delimiters: / ? # [ ] @Structure the URL. Must be encoded when used as data inside a component.
Reserved — sub-delimiters! $ & ' ( ) * + , ; =Have meaning in some components (e.g. & and = in a query). Encode when in doubt.
Everything elsespace, ", %, <, >, \, ^, `, {, |, }, control characters, non-ASCIIAlways percent-encoded.

Common examples

CharacterEncodedCharacterEncoded
space%20 (or + in forms);%3B
$%24=%3D
&%26?%3F
+%2B@%40
,%2C#%23
:%3A/%2F
%%25"%22
< / >%3C / %3Eline break%0A (or %0D%0A)
é (UTF-8)%C3%A9 (UTF-8)%E2%82%AC

encodeURI vs encodeURIComponent vs form encoding

ModeLeaves unencodedUse it for
URI component
encodeURIComponent()
A–Z a–z 0–9 - _ . ! ~ * ' ( )A single value that will be placed inside a URL: a query parameter value, a path segment, a fragment. This is what you want 90% of the time.
Full URI
encodeURI()
Everything above plus ; / ? : @ & = + $ , #A complete URL that already has its structure (scheme, host, path, query) and only needs spaces and non-ASCII characters escaped. It will not encode an & inside a value, so never use it for parameters.
Form encoding
application/x-www-form-urlencoded
A–Z a–z 0–9 - _ . *, space becomes +Bodies of HTML form submissions (POST) and query strings built by browsers from a <form>. Java's URLEncoder and PHP's urlencode() produce this format.
RFC 3986 strictOnly the unreserved set A–Z a–z 0–9 - _ . ~OAuth 1.0 signatures, AWS request signing and other protocols that require the strict unreserved set. PHP's rawurlencode() is equivalent.
encodeURIComponent("a b&c=d/é")   // "a%20b%26c%3Dd%2F%C3%A9"
encodeURI("https://x.io/a b?q=é")   // "https://x.io/a%20b?q=%C3%A9"
new URLSearchParams({ q: "a b+c" }).toString()   // "q=a+b%2Bc"  (form encoding)
decodeURIComponent("caf%C3%A9")     // "café"

Decoding tip: decodeURIComponent() throws a URIError on malformed input such as a lone % or an invalid UTF-8 sequence. This tool is more forgiving: it decodes every valid %XX pair, keeps invalid ones literally and reports a warning.