X Xerobit

URL Encoding Special Characters — Which Characters to Encode and When

URL encoding converts special characters to percent-encoded sequences (%20, %26, etc.). Here's which characters require encoding in query strings vs path segments, and how to...

Mian Ali Khalid · · 5 min read
Use the tool
URL Encoder / Decoder
Percent-encode and decode URLs per RFC 3986.
Open URL Encoder / Decoder →

URL encoding (percent-encoding) converts characters that have special meaning in URLs — or that aren’t valid URL characters — into %XX sequences where XX is the hexadecimal ASCII code. Getting encoding right prevents broken links, security vulnerabilities, and API failures.

Use the URL Encoder to encode and decode URL components online.

Why URL encoding is necessary

URLs have reserved characters with structural meaning:

https://example.com/path?key=value&key2=value2#fragment
         └─────────┘     └───┘ └────┘└───────────────┘
          path chars      query key=value pairs

If your data contains &, =, ?, or #, they must be encoded to avoid being interpreted as URL structure.

Example problem:

// Query parameter with unencoded &:
https://api.com/search?q=fish & chips&format=json

// The & splits into two parameters:
q = "fish "
" chips" = "json"  (fragment after second &)

// Correct (& encoded as %26):
https://api.com/search?q=fish%20%26%20chips&format=json

Characters by URL position

Path segments

Characters safe to use in path segments (no encoding needed):

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

Characters that MUST be encoded in path segments:

Space → %20
? → %3F
# → %23
[ ] → %5B %5D
% → %25 (if literal percent needed)

Query string values

In query string values (?key=value), additional characters need encoding:

Space → %20 or +
& → %26
= → %3D
+ → %2B (if + is literal, not space)
# → %23
% → %25

Fragment identifier

After #, the fragment is not sent to servers (browser-only), but encoding still applies for non-ASCII characters.

RFC 3986 unreserved characters

These characters NEVER need encoding:

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

All other characters either:

  • Are reserved and have special meaning (/ ? # : @ ! $ & ' ( ) * + , ; =)
  • Or must be percent-encoded if used as data

JavaScript encoding functions

JavaScript provides multiple encoding functions — choose the right one:

// encodeURIComponent — encode a single value/parameter:
encodeURIComponent('hello world');       // 'hello%20world'
encodeURIComponent('price=10&tax=1');    // 'price%3D10%26tax%3D1'
encodeURIComponent('https://example.com'); // 'https%3A%2F%2Fexample.com'

// encodeURI — encode a full URL (doesn't encode URL structure chars):
encodeURI('https://example.com/path?q=hello world');
// 'https://example.com/path?q=hello%20world'
// (/ : ? = are NOT encoded because they're URL structure)

// URLSearchParams — the cleanest way for query strings:
const params = new URLSearchParams({
  q: 'fish & chips',
  format: 'json',
  page: '1',
});
console.log(params.toString());
// 'q=fish+%26+chips&format=json&page=1'
// Note: URLSearchParams uses + for spaces (application/x-www-form-urlencoded)

// Build full URL:
const url = new URL('https://api.example.com/search');
url.searchParams.set('q', 'hello & world');
url.searchParams.set('lang', 'en');
console.log(url.toString());
// 'https://api.example.com/search?q=hello+%26+world&lang=en'

When to use which function

// Encoding a query string value:
const searchTerm = 'fish & chips';
const url = `https://api.com/search?q=${encodeURIComponent(searchTerm)}`;

// Building query strings (best practice):
const params = new URLSearchParams({ q: searchTerm, page: 1 });
const url = `https://api.com/search?${params}`;

// Never use encodeURI for individual values:
encodeURI('fish & chips');  // 'fish%20&%20chips' — & NOT encoded! Bug!

// Encoding a path segment:
const slug = encodeURIComponent('hello world');  // 'hello%20world'
const url = `https://example.com/posts/${slug}`;

Python encoding

from urllib.parse import quote, quote_plus, urlencode, urlparse

# Encode a path segment (safe chars are preserved):
quote('hello world')         # 'hello%20world'
quote('fish & chips')        # 'fish%20%26%20chips'

# Encode a query string value (+ for spaces):
quote_plus('fish & chips')   # 'fish+%26+chips'

# Encode multiple query parameters:
params = {'q': 'fish & chips', 'format': 'json', 'page': 1}
urlencode(params)  # 'q=fish+%26+chips&format=json&page=1'

# Build a URL:
from urllib.parse import urlunparse, urlencode

base = 'https://api.example.com/search'
query = urlencode({'q': 'hello & world', 'page': 1})
url = f'{base}?{query}'
# 'https://api.example.com/search?q=hello+%26+world&page=1'

# Decode:
from urllib.parse import unquote, unquote_plus
unquote('hello%20world')     # 'hello world'
unquote_plus('hello+world')  # 'hello world'

Common encoding mistakes

Double encoding:

// WRONG: encoding already-encoded string:
const encoded = encodeURIComponent('hello%20world');
// 'hello%2520world' — %20 becomes %2520!

// CORRECT: only encode the original value:
const encoded = encodeURIComponent('hello world');
// 'hello%20world'

Not encoding user input in URLs:

// WRONG — XSS risk if user controls search:
const url = `https://example.com/search?q=${userInput}`;

// CORRECT:
const url = `https://example.com/search?q=${encodeURIComponent(userInput)}`;

Using encodeURI for query values:

// WRONG: encodeURI doesn't encode & = ?
const url = `https://api.com/?key=${encodeURI('a=b&c=d')}`;
// 'https://api.com/?key=a=b&c=d' — & creates new parameter!

// CORRECT:
const url = `https://api.com/?key=${encodeURIComponent('a=b&c=d')}`;
// 'https://api.com/?key=a%3Db%26c%3Dd'

Decoding URL components

// Decode:
decodeURIComponent('hello%20world');  // 'hello world'
decodeURIComponent('fish%20%26%20chips');  // 'fish & chips'

// Read query parameters from current URL:
const params = new URLSearchParams(window.location.search);
const q = params.get('q');  // Automatically decoded

// Parse a full URL:
const url = new URL('https://api.com/search?q=fish+%26+chips&page=2');
console.log(url.searchParams.get('q'));  // 'fish & chips' (decoded)

Related posts

Related tool

URL Encoder / Decoder

Percent-encode and decode URLs per RFC 3986.

Written by Mian Ali Khalid. Part of the Dev Productivity pillar.