What URL encoding is
URLs can only contain ASCII characters. That's the full constraint. Any character outside that set — a space, an ampersand, a hash, a non-Latin letter — breaks the URL or changes its meaning entirely. Percent-encoding (formally defined in RFC 3986) is the fix: each unsafe byte gets replaced by a percent sign followed by two hexadecimal digits. A space becomes %20. A left curly brace becomes %7B.
The unreserved characters — A–Z, a–z, 0–9, -, _, ., ~ — never need encoding. Everything else is context-dependent.
Why special characters need encoding
Some characters are reserved because URLs use them as structure. The ampersand (&) separates query parameters. The equals sign (=) binds a key to its value. The hash (#) marks a fragment. Send any of those inside a parameter value without encoding and the browser or server reads the structure incorrectly — your data gets truncated or misrouted.
Consider a search query for the phrase price=100&tax. Put that raw into a URL and the server sees three separate parameters. Encode it as price%3D100%26tax and it arrives as a single string. That's the entire reason encoding exists.
Non-ASCII characters — accented letters, Arabic, Japanese, emoji — get encoded as their UTF-8 byte sequences. The emoji 😀 encodes to %F0%9F%98%80: four bytes, four percent-encoded pairs.
Encoding vs decoding
Encoding takes a raw string and replaces every unsafe character with its percent-encoded form. Decoding does the reverse: reads each %XX sequence and substitutes the corresponding character. Both operations are lossless — encode then decode and you're back to the original string.
The direction you need depends on what you're holding. Got a raw string you need to put inside a URL? Encode it. Got a URL-encoded string you need to read? Decode it. The URL Encoder / Decoder handles both in one place — paste your input and pick the operation.
How to encode and decode URLs
Encoding manually: take each character, check whether it's in the unreserved set, and if not, write its UTF-8 byte(s) as %HH pairs. That's tedious for anything longer than five characters. In JavaScript, encodeURIComponent() handles it correctly for query parameter values — it encodes everything except the unreserved characters. encodeURI() is a different function: it preserves the structural characters (/, :, ?, #), so it's for encoding a complete URL, not a value inside one.
In PHP, urlencode() encodes spaces as + rather than %20 — fine for query strings, wrong for path segments. rawurlencode() always uses %20 and follows RFC 3986. Know which you need before you reach for one.
Decoding: most languages have a direct inverse. JavaScript has decodeURIComponent(). PHP has urldecode() and rawurldecode(). If you just need to inspect an encoded URL quickly, the URL Encoder / Decoder tool is faster than writing a one-off script.
Characters that always need encoding
These are the ones that break URLs most often in practice:
%20— space (sometimes+in query strings only)%26— ampersand (&)%3D— equals sign (=)%23— hash / number sign (#)%3F— question mark (?)%2F— forward slash (/)%3A— colon (:)%2B— plus sign (+), since+decodes to a space in query strings
The plus-sign trap catches developers regularly. If your data contains a literal +, encode it as %2B before it goes into a query string — otherwise it arrives at the server as a space.
For tasks involving encoded binary data rather than URL components, Base64 encoding is a separate mechanism with different rules. And if you're encoding HTML special characters (<, >, &) for display inside a web page rather than inside a URL, that's a different job: HTML entity encoding.
URL encoding in practice
The single most common mistake: encoding the entire URL instead of just the parameter values. The slashes and colons in https://example.com/search?q= are structural and must not be encoded. Only the value after the = gets encoded. Get the boundary wrong and the URL stops resolving.
Paste any string into the URL Encoder / Decoder, encode or decode in one click, and copy the result. No libraries, no runtime, nothing to install.