DevGizmo
Back to Blog
string·

URL Encoding Explained: Percent-Encoding and When to Use It

URL encoding (percent-encoding) ensures special characters are safely transmitted in URLs and query strings. Learn which characters need encoding, how the algorithm works, and the difference between encodeURI and encodeURIComponent.

url-encodingpercent-encodinghttpjavascript

Why URLs Need Encoding

A URL can only contain a limited set of characters defined in RFC 3986. Characters outside this set — spaces, non-ASCII letters, certain punctuation — must be encoded before they appear in a URL.

If you try to include a space in a URL without encoding it, browsers typically replace it with + or %20, but servers and libraries interpret these differently. Being explicit with encoding prevents subtle bugs, broken links, and security issues.

How Percent-Encoding Works

Percent-encoding replaces each unsafe byte with a percent sign followed by two hexadecimal digits representing that byte's value:

Space (0x20) → %20
é  (U+00E9, UTF-8: 0xC3 0xA9) → %C3%A9
# (0x23) → %23

For multi-byte Unicode characters, the character is first converted to UTF-8, then each byte is percent-encoded individually.

Safe vs Unsafe Characters

Always safe (no encoding needed): Letters A–Z, a–z, digits 0–9, and the four unreserved symbols: -, _, ., ~

Reserved characters have special meaning in URLs and should be encoded when used as data:

CharacterEncodedURL meaning
#%23Fragment identifier
?%3FQuery string start
&%26Query parameter separator
=%3DParameter key/value separator
/%2FPath separator
+%2BTreated as space in form data (application/x-www-form-urlencoded)
@%40Userinfo delimiter

JavaScript: encodeURI vs encodeURIComponent

JavaScript has two built-in encoding functions, and choosing the wrong one is a common mistake.

encodeURI(url)

Encodes a complete URL. It does not encode characters that are valid URL structure characters (/, ?, #, &, =, :):

encodeURI("https://example.com/search?q=hello world&lang=en");
// "https://example.com/search?q=hello%20world&lang=en"

encodeURIComponent(value)

Encodes a URL component — a single parameter value or path segment. It encodes reserved characters too:

encodeURIComponent("hello world & goodbye");
// "hello%20world%20%26%20goodbye"

// Correct way to build a query string:
const q = encodeURIComponent(userInput);
const url = `https://example.com/search?q=${q}`;

Rule of thumb: Use encodeURIComponent for individual query parameter keys and values. Use encodeURI only for full URLs where you want to preserve the URL structure.

The URLSearchParams API

In modern JavaScript, the cleanest way to build query strings is with URLSearchParams. It handles encoding automatically:

const params = new URLSearchParams({
  q: "hello world",
  lang: "en",
  tags: "c++ & python",
});
console.log(params.toString());
// "q=hello+world&lang=en&tags=c%2B%2B+%26+python"

Note that URLSearchParams uses + for spaces (form encoding), while encodeURIComponent uses %20. Both are valid in query strings, but choose one and be consistent.

Decoding

Decoding is the reverse operation:

decodeURIComponent("hello%20world%20%26%20goodbye");
// "hello world & goodbye"

Always decode values received from URL parameters before using them — but do so after parsing, not before. Decoding before parsing can turn an encoded %2F into /, which would corrupt the URL structure.

Security Considerations

Never construct URLs by concatenating unencoded user input. This can allow path traversal attacks or open redirects:

// UNSAFE — user input can inject arbitrary path segments
const url = `/user/${userId}/profile`;

// SAFE
const url = `/user/${encodeURIComponent(userId)}/profile`;

In server-side code, use a trusted URL-building library rather than string concatenation. In browser JavaScript, use URL and URLSearchParams.

Double-Encoding

A common bug is double-encoding values — encoding an already-encoded string. This turns %20 into %2520 (because % itself gets encoded to %25). Always track whether a value has already been encoded, and decode before re-encoding if needed.

Try it yourself

Put these concepts into practice with the free online tool on DevGizmo.