Skip to content

URL Encoder & Decoder

Percent-encode or decode URLs and query strings as a single value (encodeURIComponent) or whole URL (encodeURI). Split a URL into protocol, host, path, params.

Direction
0 characters · 0 lines
Encoding type
encodeURIComponent escapes everything, including URL delimiters like /, ?, & and #, so use it for a single query parameter value. encodeURI leaves those delimiters alone and escapes only the rest, so use it for a complete URL. Example: "a b/c?d" → Single value gives "a%20b%2Fc%3Fd", Whole URL gives "a%20b/c?d".

0 characters · 0 lines

URL structure parser

URL structure parser

Enter a full URL to see it split into protocol, host, path, and query parameters.

https://example.com/path?query=1&lang=ko

What you enter is processed only in this browser and is never sent to a server. How it works

URL encoding and decoding between hello world and hello%20world

How to use it

There are two tools on this page. The one at the top encodes or decodes a string. The one below it, “URL structure parser”, takes one complete URL and shows it part by part. Neither affects the other.

For the top one, choose “Encode” or “Decode” under “Direction”, then set two things.

  • Encoding type: “Single value” is for a piece you’re going to slot into a URL, such as the value of a query parameter. “Whole URL” is for a string that already has the shape of an address. The next section explains the difference.
  • + as space (application/x-www-form-urlencoded): turn it on only when you’re working with data submitted by an HTML form.

When encoding, what you type in “Original text” comes out in “Encoded result”. When decoding, “Encoded string” becomes “Decoded result”. Encoding € gives %E2%82%AC. This character is 3 bytes in UTF-8, so it turns into three %XX groups. “Send result to decode input” and “Send result to encode input” move the result you just got into the input of the opposite direction.

“Single value” and “Whole URL” leave different characters alone

Both types replace characters that can’t appear in a URL as they are with % followed by two hex digits (percent-encoding). Where they differ is in how they handle the characters that divide a URL into its parts, such as /, ?, and &. “Single value” gives the same result as JavaScript’s encodeURIComponent, and “Whole URL” the same as encodeURI.

Encoding type Characters left unchanged
Single value letters, digits, - _ . ! ~ * ' ( )
Whole URL all of the above plus ; / ? : @ & = + $ , #

Take the same input, https://example.com/café?q=crème brûlée&page=1#menü, and the two types part ways like this.

  • Whole URL: https://example.com/caf%C3%A9?q=cr%C3%A8me%20br%C3%BBl%C3%A9e&page=1#men%C3%BC
  • Single value: https%3A%2F%2Fexample.com%2Fcaf%C3%A9%3Fq%3Dcr%C3%A8me%20br%C3%BBl%C3%A9e%26page%3D1%23men%C3%BC

The first works as an address right away. The second doesn’t, but it can go into another URL whole as a parameter value (?redirect=...). In the other direction, if you put the search term a/b&c into a query value using “Whole URL”, the & is left in place and gets read as the start of the next parameter. That’s when you need “Single value”, which produces a%2Fb%26c.

Decoding has the same split. “Whole URL” doesn’t undo the encoding of the characters that divide a URL. Give it a%2Fb%3Fc%26d%23e%20f and “Single value” returns a/b?c&d#e f, while “Whole URL” returns a%2Fb%3Fc%26d%23e f. If you decode something and %2F or %26 is still there, try switching the encoding type to “Single value”.

One thing worth remembering: even “Single value” leaves ! ' ( ) * unchanged. If the value is going to a server that insists on those being encoded too, replace them in the result yourself with %21, %27, %28, %29, and %2A.

+ as space

Data sent by an HTML <form> (application/x-www-form-urlencoded) writes a space as +, not %20. Turn on “+ as space” when you’re producing or reading that format.

Direction Input Option off Option on
Encode (Single value) a+b c a%2Bb%20c a%2Bb+c
Encode (Whole URL) a+b c a+b%20c a%2Bb+c
Decode (Single value) a+b%2Bc a+b+c a b+c

With the option on, a + that was in the original becomes %2B so it can’t be mistaken for a space. “Whole URL” normally leaves + alone, but with this option on it changes it to %2B in the same way. When decoding with the option off, + is just +. If you decode a value copied from a search results address, such as q=crème+brûlée, and the + is still there, that’s a case for turning the option on. In a URL path or a file name + doesn’t mean a space, so leave it off there.

What the URL structure parser shows

Enter a complete URL that starts with a protocol such as https:// in the “Full URL” field and you get “Protocol”, “Host”, and “Path”, plus “Query string” and “Hash” when the URL has them. The table underneath lists the query parameters one per row as “Key” and “Value (decoded)”. Without a protocol, as in example.com/path, you see “This isn’t a complete URL with a protocol (like https://).”

The values shown are not your input character for character. They’re what the browser has after parsing and normalizing the URL. Enter https://Example.COM:443/a/../b/café?q=hello%20world&tag=a&tag=b&x=1+2#top and you get the following.

Item Value shown How it differs from the input
Protocol https
Host example.com lowercased, and 443, the default port for https, is dropped
Path /b/caf%C3%A9 /a/.. is resolved and é appears in encoded form
Query string ?q=hello%20world&tag=a&tag=b&x=1+2 same as the input
Hash #top

The table has four rows: q = hello world, tag = a, tag = b, and x = 1 2. A key that appears more than once gets a row each time. As the value of x shows, this table always reads + as a space, whatever the “+ as space” checkbox at the top is set to. That’s because the URL standard’s rule is to parse a query string as form data.

Two more things to know. A domain name with non-ASCII characters appears in “Host” as Punycode (https://café.example/ → xn--caf-dma.example). And when an address carries a username and password, as in http://user:pw@host:8080/p, that part isn’t shown under any item, and “Host” shows only host:8080.

Input that fails to decode

Decoding succeeds only when every % is followed by two hex digits and the bytes they add up to form UTF-8 characters. If anything is off, there’s no result, just a message that begins “The percent-encoding isn’t valid.”

Input Why it fails
100% Nothing follows the %. A literal percent sign has to be written as %25
%zz zz isn’t a hex number
%E2%82 The last byte of the 3-byte character € (%E2%82%AC) is missing. This happens when a long address is copied only partway

Encoding never fails. Input that can’t stand as a character on its own, like half of an emoji, is encoded as the replacement character (%EF%BF%BD) and doesn’t raise an error.

Sources

Frequently asked questions

What happens if I encode a string that's already encoded?

Each % becomes %25, and you end up with double encoding. Encode %20 with Single value and you get %2520, and decoding that once gives %20, not a space. If an address shows %25 again and again, or a decoded result still has %XX in it, something encoded it twice along the way. Keep decoding until the original text appears. The button that sends the result to the decode input lets you chain those steps.

A string like caf%E9 from an old site's address won't decode.

That address was built with a character encoding other than UTF-8. This tool reads the bytes written as %XX as UTF-8 only, and treats byte sequences that don't fit UTF-8 as an invalid percent-encoding error. The old notation that starts with %u, such as %u00e9, gives the same error. Strings like these can't be reversed with this tool.

Does the URL structure parser show an error for a URL with broken percent-encoding?

No. The decoder at the top rejects the whole input if even one % is wrong, but the URL structure parser reads as much as it can. Enter https://example.com/?q=%zz&r=%E2%82 and the value of q is shown as %zz unchanged, while the value of r is shown as the replacement symbol for a broken character (�). Bytes that cannot be decoded as UTF-8 may appear as this symbol. Check for a truncated value or a different character encoding. The symbol may also have been in the original text, so its presence alone does not identify the cause.

Last updated: