A URL can only carry a small set of plain ASCII characters. Anything else, like a
space, an accented letter or an emoji, has to be written as a percent sign and the
hex value of each of its UTF-8 bytes: é becomes %C3%A9. That is URL encoding,
also called percent encoding, and decoding turns it back into readable text.
encodeURI: a whole URL. Keeps : / ? # & = so the URL still works.
Runs in your browser. Nothing you type is uploaded.
Query string in the input box
| # | Key | Value |
|---|---|---|
| 1 | q | café menu |
| 2 | tagrepeated | 🐱 |
| 3 | tagrepeated | cats |
Type in the left box and it converts as you go. Pick Component for one piece
of a URL, such as a query value, Full URL for a whole address you want to keep
working, or Form for the +-for-space style HTML forms use. Switch to
Decode to read an encoded link, and use Decode this to send the result back
round for a round trip. Whatever is in the input box, its query string is listed
underneath as a table, decoded, with repeated keys marked.
Which rules to pick
The three settings differ in what they leave alone, and the choice is the most common source of broken links.
| Component | Full URL | Form | |
|---|---|---|---|
| Browser function | encodeURIComponent | encodeURI | URLSearchParams |
| Use it for | One value, key or path segment | A complete address | A form body or query string |
| Space becomes | %20 | %20 | + |
/ ? # & = : @ | Escaped | Left alone | Escaped |
+ | %2B | Left alone | %2B |
! ' ( ) ~ * | Left alone | Left alone | ! ' ( ) ~ escaped |
A value that goes inside a URL always wants Component. A whole URL that is only being tidied, say one with a space in the path, wants Full URL.
| Input | Component | Full URL |
|---|---|---|
cats & dogs? | cats%20%26%20dogs%3F | cats%20&%20dogs? |
https://a.com/?q=1 | https%3A%2F%2Fa.com%2F%3Fq%3D1 | unchanged |
café 🐱 | caf%C3%A9%20%F0%9F%90%B1 | caf%C3%A9%20%F0%9F%90%B1 |
Characters you will meet
| Character | Encoded | Why it matters |
|---|---|---|
| space | %20, or + in a form | Not allowed in a URL |
& | %26 | Separates query parameters |
= | %3D | Separates a key from its value |
? | %3F | Starts the query string |
# | %23 | Starts the fragment, which is never sent to the server |
/ | %2F | Separates path segments |
+ | %2B | Read as a space in a query string |
% | %25 | Starts every escape, so it has to be escaped itself |
Gotchas
- Encode the pieces, then join them. Encode each value on its own and put the
&and=between them afterwards. Encoding the finished URL with Component escapes the slashes and breaks it. - Do not encode twice.
%20encoded again is%2520. If a link is full of%25, decode it once more. - Plus is not always a space. Only in a query string or a form body. In a path,
a+breally is a plus. - Decoding Full URL leaves some escapes.
decodeURIkeeps%2F,%3F,%23and the rest of the reserved set as they are, because decoding them would change what the URL means. Use Component to decode everything. - The fragment is not sent to the server. What follows
#stays in the browser, so a server log will not show it.
Step by step
- Convert the text to bytes. For text that means UTF-8, which is what every browser uses.
- Leave the characters the chosen rules call safe alone. Letters, digits and
- _ .are safe in all three. Component also leaves! ' ( ) * ~, Full URL leaves those plus the URL's own punctuation (: / ? # & = @ + $ , ;), and Form escapes! ' ( ) ~too. - Write every other byte as
%followed by two hex digits. - For form encoding, then turn each
%20into+.
é is two bytes in UTF-8, 0xC3 0xA9, so it becomes %C3%A9. A cat emoji is four,
0xF0 0x9F 0x90 0xB1, so it becomes %F0%9F%90%B1.
Related
- Base64 Encoder and Decoder, for turning bytes into text that is safe to carry in a URL. Its URL-safe setting is the base64 cousin of percent encoding.
- JSON Formatter and Validator, for the JSON you have just decoded out of a query parameter.
- The JavaScript cheat sheet for
encodeURIComponent,URLandURLSearchParams. - The HTML cheat sheet for forms, which is where the plus-for-space style comes from.
Common questions
What is the difference between encodeURI and encodeURIComponent?
encodeURI is for a whole URL, so it leaves the characters that give a URL its structure alone: colon, slash, question mark, hash, ampersand and equals. encodeURIComponent is for one piece, such as a query value, so it escapes those too and the piece cannot change the shape of the URL around it. Using encodeURI on a value is the classic bug: an ampersand in the value survives and starts a new parameter.
Should a space be %20 or +?
In the path of a URL it is always %20. In a query string both are read as a space by almost every server, and the plus form is what HTML forms and URLSearchParams write. That is why the Form setting writes a plus and why a literal plus sign has to become %2B. When in doubt, %20 is understood everywhere.
Why does a URL need encoding at all?
A URL may only contain a small set of ASCII characters, and some of those, like question mark and ampersand, have a job. Anything else, such as a space, an accented letter or an emoji, is written as the percent sign followed by the hex value of each of its UTF-8 bytes. The server reverses it to get the original text back.
What is double encoding?
Encoding text that is already encoded. The percent sign becomes %25, so %20 turns into %2520 and decodes back to the literal text %20 instead of a space. If a link shows %25 where you expected a space, it was encoded twice. Decode it once more.
Why does the decoder say a percent sequence is malformed?
A percent sign must be followed by exactly two hex digits. A truncated link, a stray percent sign in plain text such as 50% off, or a character cut off mid-copy all break that rule. The message shows where it happened. If the percent sign is meant literally, write it as %25.
Does it handle emoji and non-English text?
Yes. Text is converted to UTF-8 first, so an accented letter is two percent-escapes, most Chinese and Japanese characters are three, and an emoji is four. Decoding reverses it exactly. Bytes that are not UTF-8, such as an old Latin-1 link, are reported rather than shown as garbage.
Is anything I paste here sent to a server?
No. Encoding, decoding and the query string table all run in your browser and neither box is submitted anywhere. The site records that the tool was used, which setting was picked and how long the input was, so we know which tools are worth building next. The text itself is never part of that.