What Is URL Encoding (Percent-Encoding)?
A URL can only safely carry a limited set of characters. Under the RFC 3986 standard, the characters that can be used directly in a URL are limited to English letters, digits and a few marks (- _ . ~); everything outside that — a space, non-ASCII letters (ü, ı, ş, ğ, ö, ç), signs such as &, = or %, or any Unicode character — cannot be placed safely inside a URL in raw form. A space in a query string can be confused with the & character that separates parameters, and a Unicode character may be interpreted differently by different systems.
URL encoding (percent-encoding) solves this problem: it converts every disallowed character into a hexadecimal code of the form %XX corresponding to that character's byte value. The URL then becomes text made up only of safe ASCII characters, interpreted the same way everywhere.
How Does Percent-Encoding Work?
Encoding works on the character's UTF-8 bytes. A character in the ASCII range (English letters, digits) is a single byte, so it becomes a single %XX group; the space character, for example, always becomes %20. A multi-byte UTF-8 character becomes more than one %XX group: the letter ü consists of two bytes in UTF-8, so it is encoded as %C3%BC.
RFC 3986 divides characters into two groups. Unreserved characters — A-Z a-z 0-9 - _ . ~ — are never encoded, because they carry no special meaning in a URL structure. Reserved characters, on the other hand, are the ones that define a URL's structure (protocol, path, query, fragment), such as : / ? # [ ] @ (general delimiters) and ! $ & ' ( ) * + , ; = (sub-delimiters); depending on the context, these are either left as they are or encoded.
Let's look at a concrete example. Running encodeURIComponent("merhaba dünya") — Turkish for "hello world" — gives merhaba%20d%C3%BCnya. The space is a single-byte character, so it becomes %20; the two-byte letter ü becomes %C3%BC, matching its C3 BC bytes in UTF-8. In the end only unreserved characters (letters, digits, - _ . ~) stay as they are; everything else is converted into a code beginning with a percent sign.
The Difference Between encodeURIComponent and encodeURI
JavaScript offers two different encoding functions, and they are not interchangeable. encodeURIComponent encodes every character except the unreserved ones (A-Z a-z 0-9 - _ . ~), including URL structural characters such as &, =, ? and /. This function is designed for encoding a single value to be placed into a query parameter or a path segment — for instance, by turning an & character in user input into %26, it prevents that character from being wrongly interpreted as a parameter separator.
encodeURI, by contrast, leaves the characters that make up a URL's structure (: / ? # [ ] @ ! $ & ' ( ) * + , ; =) untouched. This function is designed for encoding a complete URL that has already been assembled and whose structure must be preserved — for example a full URL to be pasted into the address bar or shared as a link.
Both functions turn a space into %20. There is one historical exception: in data sent by classic HTML forms with application/x-www-form-urlencoded, a space is encoded as a + sign rather than %20. That is a separate rule specific to form data, not output produced by encodeURIComponent or encodeURI.
Which One Should You Use When?
| Scenario | Function to use | Why |
|---|---|---|
| The value of a query parameter (e.g. a search term) | <code>encodeURIComponent</code> | Characters inside the value such as <code>&</code>, <code>=</code> or a space are fully encoded so they cannot break the query structure |
| A complete URL that has already been assembled | <code>encodeURI</code> | The URL's structural characters such as <code>: / ?</code> are preserved, and only spaces and Unicode characters are encoded |
| Decoding an encoded URL | <code>decodeURIComponent</code> / <code>decodeURI</code> | Whichever function encoded it must be matched by its pair when decoding; otherwise some characters can be interpreted incorrectly |
Common Mistakes
- Encoding a complete URL with encodeURIComponent: the classic mistake. Structural characters such as
:and/also turn into%3A/%2F, and what you are left with is no longer a valid URL but an opaque string. Always useencodeURIfor a full URL andencodeURIComponentfor a single value to be embedded inside a URL. - Double encoding: if you encode a string that already contains
%20withencodeURIComponentagain, the%sign itself is also encoded and the result becomes a broken value such as%2520. Repeating the encode operation without checking whether a value has already been encoded ends in strange character sequences in the address bar or in API requests. - Not encoding query parameter values at all: adding text coming from a user straight into the query string (
?q=+ raw text) breaks the URL's other parameters or cuts the query short whenever the text contains&,#or a space. Every parameter value should be encoded separately withencodeURIComponentand only then joined with&. - Trying to decode broken percent-encoding:
decodeURIComponentthrows an error when it meets an invalid%XXsequence (for instance a half-finished%). In code that works with user input, this call needs to be wrapped in an error handling block.
The KEYDAL URL Encode / Decode Tool
If you are not sure whether you are encoding a value or a complete URL, seeing the difference on live examples is the fastest way to find out. KEYDAL's URL encode/decode tool lets you switch between component mode (encodeURIComponent) and full URL mode (encodeURI); it encodes or decodes the text you enter instantly, runs entirely in your browser and sends no data to any server.