What Is URL Encoding?
URL encoding, formally called percent-encoding, is the process of replacing characters that are not allowed in a URL with a percent sign (%) followed by the character's two-digit hexadecimal byte value. For example, a space becomes %20, an ampersand becomes %26, and a forward slash becomes %2F.
This encoding is required by RFC 3986 (Uniform Resource Identifiers) to ensure URLs are transmitted correctly across all HTTP clients, servers, proxies, and network intermediaries. Different components in a URL have different character rules — what is allowed in a path segment is different from what is allowed in a query string value.
Why Some Characters Need Encoding
A URL has a defined structure: scheme://host/path?query#fragment. Characters like ?, &, =, #, and / are structural delimiters — they separate parts of the URL. If these characters appear in a URL component's value (a query parameter value, for example), they must be encoded to prevent them from being interpreted as structure.
// Problem: ampersand in a value breaks the query string
https://example.com/search?q=fish & chips&lang=en
// The server sees: q="fish ", lang="en", and an unrecognized "chips" parameter
// Correct: encode the ampersand in the value
https://example.com/search?q=fish%20%26%20chips&lang=en
// The server sees: q="fish & chips", lang="en"
Which Characters Must Be Encoded?
RFC 3986 defines two classes of characters:
- Unreserved characters — never need encoding:
A–Z a–z 0–9 - _ . ~ - Reserved characters — structural; must be encoded when used as data:
: / ? # [ ] @ ! $ & ' ( ) * + , ; = - Everything else — including spaces, Unicode characters, and most punctuation — must always be encoded.
| Character | Encoded | Common context |
|---|---|---|
| Space | %20 (or + in forms) | Query values, path segments |
& | %26 | Values containing ampersands |
= | %3D | Values containing equals signs |
+ | %2B | When + must not mean "space" (in form encoding) |
/ | %2F | Path values, base64url strings |
@ | %40 | Email addresses in query strings |
# | %23 | Values that should not be treated as fragments |
encodeURI vs. encodeURIComponent in JavaScript
JavaScript provides two built-in functions for URL encoding, and choosing the wrong one is a very common mistake:
// encodeURI — encodes a complete URL; preserves structural characters
encodeURI("https://example.com/search?q=hello world")
// → "https://example.com/search?q=hello%20world"
// Note: &, =, ?, / are NOT encoded — they're treated as structure
// encodeURIComponent — encodes a URL component; encodes structural chars too
encodeURIComponent("hello world & more")
// → "hello%20world%20%26%20more"
// Note: &, =, ?, / ARE encoded — they're treated as data
// The correct pattern for building query strings:
const params = new URLSearchParams({
q: "fish & chips",
category: "food/seafood",
redirect: "https://example.com/page?ref=home"
});
const url = `https://example.com/search?${params}`;
// URLSearchParams handles encoding correctly for each value
Rule of thumb: Use encodeURIComponent when encoding a query parameter value or a path segment. Use encodeURI only when encoding a complete URL that has already been properly assembled. Better yet, use URLSearchParams to build query strings — it handles encoding automatically.
Form Encoding vs. Percent-Encoding
HTML forms use a related but different encoding scheme called application/x-www-form-urlencoded, where spaces are encoded as + (not %20) and newlines become %0D%0A. This is what browsers send when you submit a form with method="POST".
# HTML form submission body (application/x-www-form-urlencoded)
name=John+Doe&message=Hello+World
# Percent-encoding (RFC 3986)
name=John%20Doe&message=Hello%20World
When receiving form data in your backend, ensure your framework's form parser handles both + and %20 for spaces. Most do, but the distinction matters when you are manually parsing form bodies.
URL Encoding in Practice
curl
# Let curl handle encoding with --data-urlencode
curl -G https://api.example.com/search --data-urlencode "q=fish & chips" --data-urlencode "page=1"
# Or encode manually
curl "https://api.example.com/search?q=fish%20%26%20chips&page=1"
Python
from urllib.parse import urlencode, quote, unquote
# Encoding a single value
quote("fish & chips") # 'fish%20%26%20chips'
quote("fish & chips", safe='') # same — safe='' encodes / too
# Building a query string
params = {"q": "fish & chips", "page": 1}
urlencode(params) # 'q=fish+%26+chips&page=1'
# Decoding
unquote("fish%20%26%20chips") # 'fish & chips'
Go
import "net/url"
// Encoding a value
url.QueryEscape("fish & chips") // "fish+%26+chips"
url.PathEscape("path/segment") // "path%2Fsegment"
// Building a URL with encoded parameters
params := url.Values{"q": {"fish & chips"}, "page": {"1"}}
u := "https://api.example.com/search?" + params.Encode()
Decoding: The Reverse Operation
When your server receives a URL or form submission, the framework automatically decodes percent-encoded values before passing them to your route handler. You should never manually decode values that your framework has already decoded — double-decoding is a security risk (a technique used in some path traversal attacks).
Only manually decode when you are processing raw URL strings directly, such as when parsing redirect URIs, constructing next-hop URLs from query parameters, or reading raw request bodies without a framework.
Use the Copynix URL Encoder
When you need to quickly encode or decode a URL value during development — checking what a server receives, constructing a query string manually, or debugging a 400 Bad Request — use the Copynix URL Encoder/Decoder. It handles full UTF-8 multibyte characters, supports both standard percent-encoding and form encoding, and runs entirely in your browser without sending your data anywhere.
Summary
URL encoding exists to keep structural URL characters (?, &, =, /, #) unambiguous when they appear as part of a value. Always encode individual query parameter values with encodeURIComponent (or the equivalent in your language), never encode the full URL as a whole. Use URLSearchParams in JavaScript and the equivalent query-building utilities in other languages to handle encoding automatically and correctly.
