URL Encoder and Decoder
Percent-encode or decode text for URLs as a component, a whole URL or form data, and see the parts of any http or https address. Nothing is fetched.
Percent-encoding as encodeURIComponent does it. Use it for a single query value or path segment. A + stays a plus sign when decoding.
Also encodes ! ' ( ) *, which RFC 3986 reserves but encodeURIComponent leaves as they are.
Up to 500,000 characters. Nothing leaves your device.
How it works
Percent-encoding writes a byte as % followed by two hexadecimal digits. Text is first converted to UTF-8, so one letter can become several escapes: ş is %C5%9F. Characters that are safe in a URL are left as they are. RFC 3986 calls the always-safe set unreserved: letters, digits and - . _ ~.
The tool has three encoding types, and the right one depends on what you are encoding.
| Type | Stays as typed | Space | Use it for |
|---|---|---|---|
| Component (encodeURIComponent) | A–Z a–z 0–9 - _ . ! ~ * ' ( ) | %20 | One query value or one path segment |
| Whole URL (encodeURI) | The component set plus ; , / ? : @ & = + $ # | %20 | A complete address that already has its structure |
| Form data (WHATWG) | A–Z a–z 0–9 * - . _ | + | application/x-www-form-urlencoded, as URLSearchParams writes it |
The form type is stricter than encodeURIComponent: ~ ! ' ( ) are encoded and a literal + becomes %2B. Newlines are written as %0A, as URLSearchParams does; the CRLF an HTML form submission would use is not simulated. Strict adds ! ' ( ) * to the component type.
Decoding
Decoding reverses the escapes and reads the bytes as UTF-8. Component decoding leaves + alone; form decoding turns it into a space first. Decoding also reveals reserved characters: %2F becomes /, so the result may no longer be safe to put back into a URL without encoding it again.
Strict decoding gives an error for a % without two hex digits and for bytes that are not valid UTF-8. Lenient decoding decodes every valid piece and leaves each invalid one as typed, counting them.
The parts view
If the text you enter is an http or https address, a table shows its parts as the WHATWG URL parser sees them: scheme, host (a non-ASCII domain appears as punycode), port (empty when it is the default for the scheme), decoded path, fragment and the query split into name and value on &, with + read as a space. A user name or password in the address is flagged. Nothing is fetched.
Examples
| Text | Component | Whole URL | Form |
|---|---|---|---|
| a b | a%20b | a%20b | a+b |
| a&b=c | a%26b%3Dc | a&b=c | a%26b%3Dc |
| 1+1 | 1%2B1 | 1+1 | 1%2B1 |
| 100% | 100%25 | 100%25 | 100%25 |
| ~ | ~ | ~ | %7E |
| !'()* | !'()* | !'()* | %21%27%28%29* |
| ş ğ ı İ | %C5%9F%20%C4%9F%20%C4%B1%20%C4%B0 | %C5%9F%20%C4%9F%20%C4%B1%20%C4%B0 | %C5%9F+%C4%9F+%C4%B1+%C4%B0 |
| 😀 | %F0%9F%98%80 | %F0%9F%98%80 | %F0%9F%98%80 |
| a%20b (already encoded) | a%2520b | a%2520b | a%2520b |
With strict switched on, !'()*~ in the component type becomes %21%27%28%29%2A~.
A whole address, two ways (derived from the rules above): the text https://example.com/a b?q=ş&x=1#top encoded as a whole URL gives https://example.com/a%20b?q=%C5%9F&x=1#top, which still works as an address. Encoded as a component it gives https%3A%2F%2Fexample.com%2Fa%20b%3Fq%3D%C5%9F%26x%3D1%23top, which is right only if the entire address is itself a query value, for example in a redirect parameter.
Decoding. %C5%9F%C4%B1%F0%9F%98%80 decodes to şı😀. The string a+b%2Bc gives a+b+c as a component and a b+c as form data. In lenient mode a%zz%41%E0%A4%A b gives a%zzA%E0%A4%A b with 4 invalid sequences, 100% stays 100% with 1, and %FF%C5%9F gives %FFş with 1.
Parts. For https://example.com:8443/a%20b/%C5%9F?x=1&y=%C5%9F+z&x=2&flag&=v#sec%20tion the table shows host example.com, port 8443, path /a b/ş, fragment sec tion and the parameters x = 1, y = ş z, x = 2, flag (no value) and an unnamed parameter with value v. For https://münchen.de:443/ the host is xn--mnchen-3ya.de and the port is the scheme default.
Things to watch for
- Encode parts, not the whole URL, with the component type. Build the address from encoded pieces, and use the whole URL type only when you already have a complete address with unencoded special characters in it.
- Encode once. If
%25appears where you expected%, the input was already encoded. Decode it first, or check what the next system does to it. - Match the type to the reader. A query read by a form parser treats
+as a space. A literal plus in your data should be%2B, which the component and form types produce (the whole URL type keeps+as it is). #and&inside a value must be encoded, otherwise they end the value or the query.- Decoded text is not always URL-safe. Reserved escapes such as
%2Fand%3Fare decoded too, so the result can have a different structure if you paste it back into an address. - Lone surrogates are rejected. A text containing half of an emoji cannot be written in UTF-8 and gives an error instead of a silent replacement.
- Credentials in addresses. The parts view warns when a link carries a user name or password: they travel with the link and are visible to anyone who sees it.
- Limit. Text up to 500,000 characters; the tool never opens, fetches or sends the address you enter.
Frequently asked questions
Last updated: 10/11/2026
Related tools
Encode text to Base64 or decode it back. Text is converted as UTF-8, so ş, ğ and emoji work. Choose the URL-safe alphabet, padding and line breaks.
Generate random (v4) or time-ordered (v7) UUIDs, up to 100 at once, and check what an existing UUID contains. Everything runs in your browser.