Every character in a web address has to come from a small, safe set that browsers, servers, proxies, and logs all agree on. When you need to put something outside that set into a link - a space, an ampersand, an accented letter, or an emoji - it has to be URL encoded first. URL encoding, also called percent-encoding, is the standard that replaces those characters with a percent sign followed by their byte value in hexadecimal, so a space becomes %20 and & becomes %26. This guide explains what URL encoding is, which characters need it, how the %XX format works, and the encodeURIComponent vs encodeURI choice that trips up most developers - with worked examples you can copy.
Quick answer
URL encoding (percent-encoding) replaces characters that are unsafe or reserved in a URL with a % followed by two hexadecimal digits representing the character's byte in UTF-8. A space becomes %20, an ampersand becomes %26, and an accented e (é) becomes %C3%A9. Use encodeURIComponent for individual values you drop into a URL, and encodeURI for a full URL you do not want to break apart.
What is URL encoding?
URL encoding is a way of representing characters in a Uniform Resource Locator (URL) using only a limited, universally safe set of characters. The URL standard (RFC 3986) allows just a handful of characters to appear literally: the ASCII letters A-Z and a-z, the digits 0-9, and a few symbols. Anything else - spaces, most punctuation, and every non-English character - must be converted into a percent-encoded sequence before it can travel safely inside a link.
The reason is that URLs pass through many systems, and some characters carry special meaning to those systems. A space can be silently dropped or turned into a +, a # starts the fragment, and a ? starts the query string. Percent-encoding removes the ambiguity by turning any problematic character into a code that means "this is data, not a delimiter."
Reserved vs unreserved characters
The URL specification splits characters into groups. Knowing which is which tells you exactly what needs encoding and what should be left alone.
Unreserved characters (never encoded)
These characters are always safe to use as-is anywhere in a URL and should not be encoded:
- Uppercase letters: A-Z
- Lowercase letters: a-z
- Digits: 0-9
- Four symbols: hyphen (-), underscore (_), period (.), and tilde (~)
Reserved characters (encode when used as data)
Reserved characters have a special job in a URL - they act as delimiters that separate one part from another. They are only safe when they are doing that job. If a reserved character appears inside a value rather than as a separator, it must be encoded so it is not mistaken for a delimiter.
- Path and authority delimiters: / : @
- Query and fragment delimiters: ? # & =
- Sub-delimiters: ! $ & ' ( ) * + , ; =
For example, the & in https://example.com/search?q=cats&sort=new separates two query parameters, so it stays literal. But if you search for the phrase "cats & dogs", the & inside that value must become %26 - otherwise the server reads &dogs as a second parameter.
The %XX format explained
Percent-encoding follows one simple rule: a percent sign (%) followed by two hexadecimal digits. Those two digits are the value of a single byte written in base-16 (00 to FF, i.e. 0-255 in decimal). To encode a character, you look up its byte value and write it after the %.
- Space is 32 in decimal, which is 20 in hexadecimal - so a space becomes %20.
- The ampersand & is 38 decimal = 26 hex - so & becomes %26.
- The equals sign = is 61 decimal = 3D hex - so = becomes %3D.
- The question mark ? is 63 decimal = 3F hex - so ? becomes %3F.
Characters in the ASCII range (0-127) are a single byte, so they always encode to one %XX sequence. Characters outside ASCII are first converted to their UTF-8 bytes - which can be two, three, or four bytes - and each byte becomes its own %XX. That is why the accented letter é (U+00E9) encodes to %C3%A9: its UTF-8 form is the two bytes C3 and A9.
encodeURIComponent vs encodeURI - when to use each
JavaScript gives you two built-in functions for percent-encoding, and picking the wrong one is the most common URL-encoding mistake. The difference is which reserved characters they leave alone.
encodeURIComponent - for a single value
encodeURIComponent encodes almost everything that is not an unreserved character, including the reserved delimiters / ? : @ & = + $ #. Use it for a single piece of data you are inserting into a URL - one query-parameter value, one path segment, or a form field. Because it escapes & and =, a value that contains them will not break the surrounding query string.
encodeURI - for a whole URL
encodeURI is designed to encode a complete, already-assembled URL. It leaves the reserved delimiters intact - :, /, ?, #, &, and = pass through unchanged - so the URL keeps its structure. It only encodes characters that are never valid anywhere, like spaces. Use it when you have a full URL that may contain an illegal character and you do not want to alter its parts.
Rule of thumb
Encode the parts, not the whole. Build a URL by running encodeURIComponent on each individual value first, then join them with the &, =, /, and ? delimiters yourself. Reach for encodeURI only when you are handed a complete URL string to clean up.
Two practical notes: encodeURIComponent does not escape the characters ! ' ( ) *, so a strict parser may need those replaced manually. And never encode a string that is already encoded - doing so turns every % into %25, so %20 becomes %2520, a classic double-encoding bug that produces broken links.
Worked examples
Here is how common characters look before and after encoding. Each line reads as character - what it is - encoded form.
- Space - word separator - %20 (a + is also used for spaces in query strings; see below)
- & - ampersand - %26
- = - equals sign - %3D
- ? - question mark - %3F
- / - forward slash - %2F
- # - hash / fragment start - %23
- + - plus sign - %2B
- é - e with an acute accent (non-ASCII, 2 UTF-8 bytes) - %C3%A9
- 😀 - emoji (4 UTF-8 bytes) - %F0%9F%98%80
Encoding a value with spaces and symbols
Say you want to pass the search phrase "cats & dogs = fun" as a single query value. Running encodeURIComponent on it produces cats%20%26%20dogs%20%3D%20fun. Every space, the &, and the = are escaped, so the whole thing is treated as one value rather than three separate parameters.
A full query string example
Putting it together, imagine a search page that takes a query and a category. You encode each value separately, then assemble the URL:
- Raw query value: cats & dogs
- Raw category value: pets/animals
- Encoded query: cats%20%26%20dogs
- Encoded category: pets%2Fanimals
- Final URL: https://example.com/search?q=cats%20%26%20dogs&category=pets%2Fanimals
Notice that the & and = between q=... and category=... are left literal because they are doing their job as delimiters, while the & inside the query value and the / inside the category value are encoded because they are data. That is exactly what encoding each value with encodeURIComponent and then joining the pieces yourself gives you.
Space: %20 or +?
In the path of a URL, a space is always %20. In a query string, older form-encoding (application/x-www-form-urlencoded) uses + for a space instead. Both decode back to a space, but they are not interchangeable everywhere - when decoding, check whether the source used %20 or + so you restore the original text correctly.
Frequently asked questions
What is URL encoding in simple terms?
URL encoding is a way to safely include special characters in a web address by replacing them with a % and a two-digit code. Because URLs can only contain a limited set of characters, anything else - like a space, an ampersand, or an accented letter - is converted into its percent-encoded equivalent (a space becomes %20) so the link stays valid.
Why do URLs have %20 in them?
%20 is the percent-encoded form of a space. Spaces are not allowed in a URL, so when a link contains one - often from a file name or a search term - it is replaced with %20. When the page loads, the server or browser decodes %20 back into a space.
What is the difference between encodeURI and encodeURIComponent?
encodeURIComponent encodes a single value and escapes the reserved delimiters (& = ? / #), making it right for one query parameter or path segment. encodeURI encodes a whole URL and leaves those delimiters intact so the address keeps its structure. Use encodeURIComponent for the parts and encodeURI for a complete URL.
Which characters need to be URL encoded?
Only the unreserved characters - A-Z, a-z, 0-9, and - _ . ~ - are always safe. Everything else should be encoded when it appears inside a value: spaces, most punctuation, the reserved delimiters (/ ? : @ & = + $ , ; # ! ' ( ) *), and all non-ASCII characters like accented letters and emoji.
Is URL encoding the same as encryption or Base64?
No. URL encoding is not encryption and provides no security - it is a fully reversible text transformation that only makes characters safe to travel in a URL, and anyone can decode it instantly. It also differs from Base64, which re-encodes binary data into a 64-character alphabet for a different purpose.
How do I decode a URL-encoded string?
Reverse the process: every %XX sequence is converted back to the byte it represents, and consecutive bytes are read as UTF-8 to recover characters like é or emoji. In JavaScript, decodeURIComponent does this; a URL decoder tool does the same in your browser and shows a clear error if the input has a malformed sequence like a lone %.
Encode or decode a URL instantly
Use the free URL Encoder / Decoder to percent-encode any text or decode an encoded URL - switch between encodeURIComponent and encodeURI in one click, and everything runs in your browser.