GlobalKit

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.

TypeStays as typedSpaceUse it for
Component (encodeURIComponent)A–Z a–z 0–9 - _ . ! ~ * ' ( )%20One query value or one path segment
Whole URL (encodeURI)The component set plus ; , / ? : @ & = + $ #%20A 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

TextComponentWhole URLForm
a ba%20ba%20ba+b
a&b=ca%26b%3Dca&b=ca%26b%3Dc
1+11%2B11+11%2B1
100%100%25100%25100%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%2520ba%2520ba%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

Frequently asked questions

Last updated: 10/11/2026

Related tools