Guide
5 min read

URL encoding explained

URLs can only contain a specific set of ASCII characters. Percent-encoding is how everything else gets in: spaces, special characters, unicode text, and symbols that would otherwise break parsers. Here is exactly how it works.

URL Encoder

Encode and decode URL components instantly

Open tool

What is URL encoding?

A URL is allowed to contain only unreserved characters (letters, digits, -, _, ., ~) and a defined set of reserved characters that carry structural meaning (/ ? # [ ] @ : ! $ & ' ( ) * + , ; =). Everything else must be percent-encoded.

Percent-encoding replaces a character with a % sign followed by two hexadecimal digits representing its UTF-8 byte value. A space (byte 0x20) becomes %20. The letter "é" (UTF-8 bytes 0xC3 0xA9) becomes %C3%A9.

Reserved characters must also be encoded when they appear as data values rather than URL structure. An ampersand in a query param value must be encoded as %26, otherwise the parser reads it as a param separator.

Common encodings reference

CharacterEncodedNote
Space%20Also written as + in form data
&%26Separates query params : must be encoded in values
=%3DSeparates key from value : must be encoded in values
/%2FPath separator : encode when used as data
?%3FStarts query string : encode when used as data
#%23Fragment identifier : encode when used as data
+%2BMeans space in form encoding : encode when literal + is intended
@%40Used in email addresses and credentials
%%25The encoding character itself : must always be encoded

encodeURI vs encodeURIComponent

JavaScript gives you two built-in encoding functions, and choosing the wrong one is the most common URL encoding bug:

encodeURI()

Encodes everything except: A-Z a-z 0-9 ; , / ? : @ & = + $ - _ . ! ~ * ' ( ) #

Leaves reserved URL chars alone. Safe for encoding a complete URL.

encodeURI("https://example.com/search?q=hello world") → "https://example.com/search?q=hello%20world"

encodeURIComponent()

Encodes everything except: A-Z a-z 0-9 - _ . ! ~ * ' ( )

Encodes reserved chars like / ? & =. Safe for encoding a single query param value.

encodeURIComponent("hello & world") → "hello%20%26%20world"

The common mistake: using encodeURI() on a query parameter value. It will leave & and = unencoded, breaking the query string. Always use encodeURIComponent() for individual values.

Form encoding: application/x-www-form-urlencoded

HTML forms (and many older APIs) use a slightly different encoding called application/x-www-form-urlencoded. It is like percent-encoding but with one difference: spaces are encoded as + instead of %20. Key-value pairs are separated by &, and keys and values are separated by =.

name=Alice+Smith&message=Hello+World%21&age=30

When you see a + in a URL query string, check whether you are dealing with form-encoded data. If you are, decode it as a space. If not, it is a literal plus sign.

Unicode characters

Characters outside ASCII must be UTF-8 encoded first, then each byte is percent-encoded. The letter "é" (U+00E9) has the UTF-8 byte sequence 0xC3 0xA9, so it becomes %C3%A9 in a URL.

encodeURIComponent() handles this automatically in JavaScript. You do not need to manually convert to UTF-8 before encoding.

Worked example: building a query string correctly

Suppose your search input is "coffee & tea" and you want to sort by "price/asc". Both values contain reserved characters that must be encoded before they go into the URL:

const query = 'coffee & tea'
const sort  = 'price/asc'
const url   = `https://example.com/search?q=${encodeURIComponent(query)}&sort=${encodeURIComponent(sort)}`
// https://example.com/search?q=coffee%20%26%20tea&sort=price%2Fasc

The & and / inside the values are safely encoded so the URL parser does not misread them as structural characters. The & separating the two params is left raw because it is structural.

Frequently asked questions

Why does + sometimes mean a space?

In the application/x-www-form-urlencoded format (used by HTML forms and many older APIs), + is an alternative encoding for a space character. In standard percent-encoding (RFC 3986), + is a literal plus sign and space is always %20. When you see + in a query string, the server decodes it as a space only if it is parsing form-encoded data.

When should I use encodeURIComponent vs encodeURI?

Use encodeURIComponent when encoding a single value that will be placed inside a URL: a query parameter value, a path segment, or a hash fragment. Use encodeURI only when you have a full URL that is already correctly structured and you just need to escape unsafe characters without breaking its structure. In practice, encodeURIComponent is the one you will use most.

Is %20 or + correct for spaces in URLs?

Both are valid but in different contexts. %20 is the correct percent-encoding per RFC 3986 and works everywhere. + is only valid as a space in the query string portion of application/x-www-form-urlencoded data. For maximum compatibility, especially in API query parameters, prefer %20.

How do I decode a URL-encoded string in JavaScript?

Use decodeURIComponent() to decode a single encoded component: decodeURIComponent("hello%20world") returns "hello world". Use decodeURI() if you encoded a full URL with encodeURI(). The browser also exposes the URL API (new URL(str)) which parses and decodes a complete URL into its components.

What happens with double encoding?

Double encoding occurs when you encode an already-encoded string. The % in %20 itself gets encoded to %2520, so the server receives the literal text "%20" rather than a space. This is a common bug when building URLs by concatenating strings. Always encode raw values, never pre-encoded ones.

Encode and decode URLs instantly

Paste any string to encode it for safe use in a URL, or decode a percent-encoded value.

Open URL Encoder