Dev / IT5 min read

URL Encoding Explained: Percent-Encoding, encodeURI vs encodeURIComponent

Understand URL encoding (percent-encoding) — why it exists, how %20 and other sequences work, and the critical difference between encodeURI and encodeURIComponent in JavaScript.

Every time you search Google, share a link, or call an API with query parameters, URL encoding is working silently in the background. Understanding it prevents bugs in web applications and APIs — especially when dealing with special characters, Thai text, and query strings.

What is URL Encoding?

URLs can only contain a safe subset of ASCII characters. Characters outside this safe set — spaces, Thai letters, symbols like &, =, and # — must be encoded before being placed in a URL. This encoding is called percent-encoding because each unsafe character is replaced by a % sign followed by its two-digit hexadecimal ASCII code.

For example:

  • Space → %20 (ASCII 32 = 0x20)
  • &%26
  • =%3D
  • #%23
  • Thai ก → %E0%B8%81 (UTF-8 encoded, then percent-encoded)

Characters That Don't Need Encoding

The following characters are "unreserved" and are safe to use in URLs without encoding:

A–Z  a–z  0–9  -  _  .  ~

Everything else — including spaces, Thai characters, emoji, and most punctuation — must be encoded when used in a URL value.

encodeURI vs encodeURIComponent

JavaScript provides two built-in functions for URL encoding. Choosing the wrong one is one of the most common sources of URL-related bugs.

encodeURI()

Encodes a complete URL. It leaves characters that are legal in a URL structure untouched — things like /, ?, &, #, and : — because removing those would break the URL's meaning.

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

// These are NOT encoded by encodeURI:
// : / ? # [ ] @ ! $ & ' ( ) * + , ; =

encodeURIComponent()

Encodes a single value to be placed inside a URL — a query parameter value, a path segment, or a fragment. It encodes everything except A–Z a–z 0–9 - _ . ~, including all the URL-structural characters that encodeURI skips.

encodeURIComponent('hello world & more')
// → 'hello%20world%20%26%20more'

encodeURIComponent('https://example.com')
// → 'https%3A%2F%2Fexample.com'
// (note: the :// are also encoded — correct for a value)

The Rule of Thumb

  • Use encodeURIComponent() on parameter values before appending them to a URL.
  • Use encodeURI() only if you have a complete URL string with no pre-encoded components.
  • In practice, URLSearchParams handles encoding automatically and is the safest approach.
// Best practice — use URLSearchParams
const params = new URLSearchParams({
  q: 'hello world',
  lang: 'th',
  ref: 'https://example.com',
})
const url = `https://api.example.com/search?${params}`
// → https://api.example.com/search?q=hello+world&lang=th&ref=https%3A%2F%2Fexample.com

Note: URLSearchParams encodes spaces as + rather than %20. Both are valid in query strings; most servers accept either.

Decoding URL-Encoded Strings

The corresponding decode functions are:

decodeURI('hello%20world')           // → 'hello world'
decodeURIComponent('hello%20world')  // → 'hello world'

// Decode a full URL
decodeURI('https://example.com/path?q=hello%20world')
// → 'https://example.com/path?q=hello world'

Thai Characters and URL Encoding

Thai characters are multi-byte in UTF-8. The string "สวัสดี" becomes a sequence of percent-encoded UTF-8 bytes:

encodeURIComponent('สวัสดี')
// → '%E0%B8%AA%E0%B8%A7%E0%B8%B1%E0%B8%AA%E0%B8%94%E0%B8%B5'

Modern browsers handle this transparently — the address bar displays "สวัสดี" even though the underlying request uses the percent-encoded form. APIs, however, receive the encoded form and must decode it on the server side.

Common URL Encoding Mistakes

MistakeProblemFix
Not encoding & in valuesServer splits parameter at the &Use encodeURIComponent() on each value
Double-encoding%20 becomes %2520Decode first if input might already be encoded
Using encodeURI on a value& and = aren't encoded, breaking paramsUse encodeURIComponent() for values
Not encoding spaces in pathsSome servers reject paths with literal spacesEncode spaces as %20 in paths

URL Encoding in Other Languages

# Python
from urllib.parse import quote, urlencode

quote('hello world')                    # → 'hello%20world'
urlencode({'q': 'hello world', 'n': 5}) # → 'q=hello+world&n=5'

# PHP
urlencode('hello world')  // → 'hello+world'
rawurlencode('hello world') // → 'hello%20world'

# Go
url.QueryEscape("hello world")   // → "hello+world"
url.PathEscape("hello world")    // → "hello%20world"

TRY THE FREE TOOL

URL Encode / Decode

Encode special characters for safe URL usage

Open Tool →
← Back to all articles