URLs are picky. They only speak ASCII, and even within ASCII they reserve a handful of characters for structural meaning — the slash between path segments, the question mark before the query, the ampersand between parameters. Anything else needs to be wrapped in percent encoding before it travels across the wire.
What URL encoding actually is
Percent encoding is defined in RFC 3986, the same document that defines URI syntax. The rule is small: take any byte you cannot spell directly in a URI, write it as % followed by two hexadecimal digits. A space becomes %20. An ampersand inside a query value becomes %26 so it does not get mistaken for a parameter separator. A multi-byte UTF-8 character likeç becomes two percent triplets — %C3%A7 — because UTF-8 spells that character in two bytes.
RFC 3986 §2.2 splits the special characters into two buckets. gen-delims (: / ? # [ ] @) are the major structural separators. sub-delims (! $ & ' ( ) * + , ; =) carry sub-component meaning, especially inside query strings. When data you want to pass through a URI would clash with any of these as delimiters, you encode it.
A short history — why the rules look like this
The earliest URL specification, RFC 1738 (Berners-Lee, Masinter, McCahill, 1994), already carried percent encoding. The 1994 design was small and ad-hoc: a fixed list of "unsafe" characters, an "ASCII-or-percent" rule, no Unicode story because UTF-8 was still settling. RFC 1866 (1995), the original HTML 2.0 spec, added the + for space convention because typing %20 in a form post was awkward in the dial-up era.
RFC 3986 (2005) merged these and added the formal split between unreserved characters (always safe), gen-delims (structural separators), and sub-delims (sub-component separators, mostly inside query strings). The WHATWG URL Living Standard refines the model further, defining named percent-encode sets — five of them, including the component set used by encodeURIComponent and the form-encoded set used by HTML form serialisation. The takeaway: when an old API and a new API disagree on whether something should be encoded, the old one is usually RFC 1738 vintage and the new one is WHATWG. Both can be right depending on the channel.
encodeURIComponent vs encodeURI — pick the right knife
Both functions are part of every browser and every Node runtime. They differ in how much of the reserved set they touch. encodeURIComponent is strict: it escapes everything except letters, digits, and the four unreserved marks - _ . ~ (plus the historical ! * ' ( )). Use it for query values, path segments, fragment identifiers — anywhere you are dropping a string into a slot of a URI you already control.
encodeURI is more forgiving: it preserves the URI's own structural characters (/, ?, :, @, &, =, +, $, #, ,, ;) on the assumption that you are handing it a full URL and just want spaces and accents normalised. If you reach for encodeURI when you wanted encodeURIComponent, an ampersand inside a value will silently turn into a parameter separator. That class of bug is hard to catch by eye and easy to ship to production.
The + versus %20 trap
One percent-encoding question keeps coming back: should a space be %20 or +? Both are correct, in different contexts.
%20 is the RFC 3986 answer. It applies everywhere in a URI — path, query, fragment. + is the application/x-www-form-urlencoded answer. That format was first standardised in RFC 1866 as the default HTML form encoding, and the convention that a space becomes + stuck. The WHATWG URL Living Standard preserves both rules side by side: its component percent-encode set emits %20; its application/x-www-form-urlencoded percent-encode set emits + and escapes the literal + in the input.
This generator emits %20 in both variants, because encodeURIComponent and encodeURI follow RFC 3986. If you need form-style encoding, you can post-process the output by replacing %20 with + — but only when you know the consumer expects form encoding. Mixing the two on a decoder side is where most "my space turned into a plus" bugs live.
Decoding is the forgiving end of the round trip
decodeURIComponent is a superset. It accepts the output of both encodeURIComponent and encodeURI and produces the original string. There is no need to know which variant the encoder used. That is why Decode mode here has no variant toggle — one decoder covers both.
The only thing that breaks decoding is malformed percent encoding. A bare %, a %G1 sequence, an incomplete trailing %2 — any of these will raise a URIError from the underlying runtime. The widget catches that and surfaces a friendly message. The common cause is input that was copy-pasted through something that mangled the alphabet — a chat client that ate the second hex digit, a form field that decoded too eagerly. When the decoder rejects an input, re-check the source before assuming the algorithm is broken.
Where this actually matters
- Query parameters. Any time you build a search URL or a tracking link, user-supplied values go through
encodeURIComponent. An unencoded&or=in a value silently truncates the parameter on the server side. - Path segments with user content. Routes like
/users/{username}need encoding when the username can contain spaces, slashes, or accents. Same applies to OAuth state, signed URLs, anything where the path carries data. - Fragments. Single-page apps that route via the hash (
#section) still need encoding for non-ASCII content. - Multi-byte content. Asian languages, emoji, accented Latin — they all go through UTF-8 first, then percent-encode the bytes. The generator does this natively; you do not need a separate UTF-8 pre-pass.
What URL encoding is not
It is not encryption. The output is fully reversible by anyone who reads it. Putting a password or a session token into encodeURIComponent hides nothing — the intermediate proxies and the access logs see the decoded value the moment the receiver decodes it. If you need confidentiality, use TLS for transport and a real cipher for storage.
It is not Base64 either. Base64 packs arbitrary binary into a small ASCII alphabet of 64 characters; URL encoding escapes individual reserved characters from any string. If you want to put binary data into a URL safely, the right combination is Base64URL (RFC 4648 §5) followed by URL encoding only if needed — Base64URL was designed to slot into a URL without further escaping.
Privacy and client-side encoding
Every percent-encoding step in this tool runs in the browser. Nothing leaves the page. That matters more than people think for query data — the moment you paste a URL into a server-side encoder, the server has seen your tokens, your CPF, your private parameter values. A 100% client-side tool removes that surface entirely. The recent-inputs panel stores only your inputs (mode + variant + timestamp), never the encoded output, in your browser's localStorage. Clearing the panel is one click.

