URL Encode & Decode — Percent Encoding Explained

URL encoding (also called percent encoding) converts characters that are not allowed in a URL into a safe format using a % followed by two hexadecimal digits. It's required whenever you embed user input, file names, or special characters in a URL.

What is URL encoding?

URLs can only contain a limited set of ASCII characters. Any character outside that set — spaces, accented letters, symbols, non-Latin scripts — must be percent-encoded before being placed in a URL. Each byte of the character is represented as %XX, where XX is the hexadecimal byte value.

Space   →  %20
/       →  %2F
?       →  %3F
#       →  %23
&       →  %26
=       →  %3D
+       →  %2B
@       →  %40
é       →  %C3%A9   (UTF-8: two bytes)

URL encoding in JavaScript

JavaScript provides two pairs of functions for URL encoding, each with different scope:

// encodeURIComponent — encode a single value (recommended for query params)
encodeURIComponent('hello world')   // "hello%20world"
encodeURIComponent('a=1&b=2')       // "a%3D1%26b%3D2"
encodeURIComponent('https://x.com') // "https%3A%2F%2Fx.com"

// decodeURIComponent — reverse of the above
decodeURIComponent('hello%20world') // "hello world"
decodeURIComponent('%C3%A9l%C3%A8ve') // "élève"

// encodeURI — encode a full URL (preserves :, /, ?, #, &, =)
encodeURI('https://example.com/path with spaces?q=hello world')
// "https://example.com/path%20with%20spaces?q=hello%20world"

// decodeURI — reverse of encodeURI
decodeURI('https://example.com/path%20with%20spaces')
// "https://example.com/path with spaces"

Use encodeURIComponent for individual query parameter values. Use encodeURI only for complete URLs where you want to preserve the URL structure characters.

Encode query parameters correctly in JavaScript

// Wrong — encodes the = and & signs, breaking the URL structure
const bad = encodeURIComponent('https://api.example.com/search?q=hello world&lang=en')

// Correct — encode only the values
const q = encodeURIComponent('hello world')
const lang = encodeURIComponent('en')
const url = `https://api.example.com/search?q=${q}&lang=${lang}`
// "https://api.example.com/search?q=hello%20world&lang=en"

// Even better — use URLSearchParams
const params = new URLSearchParams({ q: 'hello world', lang: 'en' })
const url2 = `https://api.example.com/search?${params}`
// "https://api.example.com/search?q=hello+world&lang=en"
// Note: URLSearchParams uses + for spaces, not %20

URL encoding in Python

from urllib.parse import quote, unquote, urlencode, quote_plus, unquote_plus

# Encode a single value (safe='/' keeps slashes unencoded)
quote('hello world')          # 'hello%20world'
quote('hello world', safe='') # 'hello%20world'
quote('/path/to/file')        # '/path/to/file'  (/ preserved by default)
quote('/path/to/file', safe='') # '%2Fpath%2Fto%2Ffile'

# Decode
unquote('hello%20world')      # 'hello world'
unquote('%C3%A9l%C3%A8ve')    # 'élève'

# Encode query parameters (uses + for spaces, like HTML forms)
quote_plus('hello world')     # 'hello+world'
unquote_plus('hello+world')   # 'hello world'

# Encode a full query string from a dict
params = {'q': 'hello world', 'lang': 'en', 'page': 1}
urlencode(params)             # 'q=hello+world&lang=en&page=1'

%20 vs + for spaces

Spaces can be encoded as either %20 or +, depending on context:

ContextSpace encodingFunction
URL path segments%20encodeURIComponent
HTML form submissions (application/x-www-form-urlencoded)+URLSearchParams
Query strings (general)Either (prefer %20)

Modern APIs and browsers accept both, but %20 is more universally safe.

Characters that do NOT need encoding

These characters are safe in URLs and are left unencoded by encodeURIComponent:

A–Z  a–z  0–9  -  _  .  !  ~  *  '  (  )

All other characters — including /, ?, #,&, =, +, and any non-ASCII characters — are encoded when passed through encodeURIComponent.

Common URL encoding mistakes

  • Double-encoding — encoding an already-encoded string produces%2520 instead of %20. Always decode before re-encoding.
  • Using encodeURI on values — it preserves= and &, so query parameter values with those characters won't be properly escaped.
  • Not encoding Unicode — characters outside ASCII must be UTF-8 encoded first, then percent-encoded. Modern functions handle this automatically.

Decode a URL online

Paste any percent-encoded URL or string into the URL Encode / Decode tool to instantly encode or decode it. For Base64-encoded strings (common in JWTs and data URIs), use the Base64 tool instead.