What is URL Encoding?
URL encoding (percent-encoding) converts characters that are unsafe or have special meaning in URLs into %XX format, where XX is the hexadecimal byte value. Standardized in RFC 3986, it ensures browsers, servers, and API clients correctly parse URLs regardless of special characters in data values.
For example, a space becomes %20, and non-ASCII characters like CJK characters are encoded as multi-byte UTF-8 sequences. URL structural characters (://, /, ?, &, =) each have reserved roles, so they must be encoded when they appear as data values rather than structural delimiters.
URL Structure and Encoding Scope
URLs consist of several components, each with different encoding rules. In https://example.com/path/to/page?key=value&name=John#section, the scheme (https), host (example.com), path (/path/to/page), query (?key=value), and fragment (#section) each allow different character sets.
RFC 3986 defines unreserved characters (usable without encoding) as: uppercase and lowercase letters (A-Z, a-z), digits (0-9), hyphen (-), underscore (_), period (.), and tilde (~). All other characters require percent-encoding in any URL position.
JavaScript Encoding Functions
encodeURI() vs encodeURIComponent()
encodeURI() encodes a complete URL, preserving structural characters (:, /, ?, #, &, =) while encoding non-structural special characters (spaces, CJK characters). Use it when you have a complete URL with non-ASCII characters that need encoding.
encodeURIComponent() encodes individual URL components (query parameter values, path segments), converting nearly all special characters including structural ones. Use it when encoding parameter values before assembling a URL.
In practice, most developers use encodeURIComponent() for individual values and assemble the URL manually. Applying encodeURIComponent() to an entire URL would encode :// and /, breaking the URL.
escape() — Do Not Use
escape() is a deprecated legacy function that uses UCS-2 encoding (not UTF-8) and does not encode @, *, /, and other characters in non-standard ways. Replace any escape() calls in existing code with encodeURIComponent().
Common Pitfalls
Double Encoding
Re-encoding an already-encoded URL converts % into %25. For example, a value already encoded as %ED%99%8D becomes %25ED%2599%258D after double encoding, which the server cannot properly decode.
Double encoding commonly occurs when frameworks automatically encode parameters but developers manually encode them first. HTTP clients like axios and fetch auto-encode query parameters, so passing pre-encoded values causes this issue. Check for %25 in the Network tab to diagnose.
Space Encoding: %20 vs +
In URL paths, %20 is the RFC 3986 standard for spaces. In HTML form data (application/x-www-form-urlencoded), + represents spaces. JavaScript's encodeURIComponent() produces %20; URLSearchParams produces +. Choose based on your server's expected format.
Multilingual URLs
Non-ASCII characters are encoded as multi-byte UTF-8 sequences. A single CJK character uses 3 bytes, expanding to 9 characters when encoded (e.g., %EA%B0%80). Browsers display the decoded form in the address bar, but HTTP requests always transmit the encoded form.
IRI (Internationalized Resource Identifier, RFC 3987) allows Unicode characters directly in URLs, but actual HTTP transmission still requires percent-encoding conversion. Seeing sequences like %EA%B0%80 in server logs is normal UTF-8 percent-encoding behavior.
Reserved Character Leaks
If query parameter values contain &, =, or # without encoding, URL parsing breaks. For example, a search query "A&B" sent as ?q=A&B is parsed as q=A plus a separate parameter B, not as the intended q=A%26B.
Server-Side Encoding
Node.js uses encodeURIComponent()/decodeURIComponent(). The URLSearchParams class handles automatic query string parsing and generation.
Python uses urllib.parse.quote()/urllib.parse.unquote(). Note that quote()'s default safe parameter doesn't encode / — use quote(value, safe='') for query values.
Java uses URLEncoder.encode(), but note it encodes spaces as + instead of %20. For %20, replace + with %20 in the result, or use Java 11+'s URI class.
Debugging Tips
The most effective debugging approach is checking the actual transmitted URL in the browser DevTools Network tab. Copy the Request URL and paste it into the URL Decoder to quickly verify each parameter's encoding is correct.
If API responses show garbled characters, check for double encoding. Performing one more decode and getting normal text confirms the issue. Server-side middleware or proxies unnecessarily adding encoding is a common cause.