Skip to content
SupraIQ

Developer

What Is URL Encoding (Percent-Encoding) and When Do You Need It?

URL encoding, also called percent-encoding, replaces unsafe characters with a percent sign and hex digits; learn how it works and when to use it.

By Vigneshwaran M · 2026-10-03 · 5 min read

Note: This article was written with AI assistance and may contain inaccuracies or outdated information. Please check important details against the official sources listed below.

URL encoding, formally called percent-encoding, is a way of writing characters that are not allowed, or have a special meaning, inside a URL. Each such character is replaced by a percent sign followed by two hexadecimal digits. A space becomes %20, and an ampersand becomes %26. You need it whenever user-supplied or unusual text ends up inside a link. To try it on your own text, use the URL encoder and decoder.

Why URLs need an escape mechanism

A URL is a string with structure. Certain characters act as separators: / divides path segments, ? starts the query, & separates query parameters, = joins a name to a value and # begins the fragment. These are called reserved characters, and they are defined in RFC 3986.

That creates a problem when your data contains one of them. Imagine a search for rock & roll. If you place it in a query unchanged, as in ?q=rock & roll, the & looks like the start of a new parameter and the space is not valid in a URL at all. Percent-encoding solves this by turning the data into a form with no ambiguity: ?q=rock%20%26%20roll.

URLs were also designed around a limited set of characters. Anything outside it, such as accented letters, Devanagari, Chinese characters or emoji, has to be encoded too.

How the encoding works

The process has two steps:

  1. Convert the character to bytes using UTF-8.
  2. Write each byte as % followed by two hex digits.

A plain ASCII character is one byte, so it becomes one %XX group. The space has byte value 32, which is 20 in hex, hence %20. A character outside ASCII uses several bytes, so it produces several groups. The letter é is two bytes in UTF-8, giving %C3%A9. A text like café & tea becomes:

caf%C3%A9%20%26%20tea

Hex digits are case-insensitive in principle, so %c3%a9 and %C3%A9 mean the same thing, although uppercase is the conventional way to write them.

Which characters stay as they are

The standard defines a set of unreserved characters that never need encoding: the letters A to Z and a to z, the digits 0 to 9, and the four symbols hyphen, period, underscore and tilde. Everything else is either reserved, with a role in the URL syntax, or must be encoded.

The key idea is that whether a reserved character needs encoding depends on where it appears. A slash between path segments is syntax and stays raw. A slash that is part of a value, for instance a file name stored in a query parameter, must be written as %2F so that it is not mistaken for a separator.

Encoding in JavaScript

JavaScript offers two built-in functions with different jobs:

encodeURIComponent("a/b?c=d&e");
// "a%2Fb%3Fc%3Dd%26e"

encodeURI("https://example.com/a b?x=1&y=2");
// "https://example.com/a%20b?x=1&y=2"

encodeURIComponent is meant for a single piece of data, such as one parameter value. It encodes the separators, so the value cannot break the URL. encodeURI is meant for a complete URL that is already structured; it leaves the separators alone and only fixes the characters that cannot appear at all.

In most day-to-day code you should reach for encodeURIComponent for values, or let a helper build the query for you:

const params = new URLSearchParams({ q: "rock & roll", page: "2" });
params.toString();
// "q=rock+%26+roll&page=2"

Notice the + in that output. It brings us to the most common point of confusion.

Space: %20 or +?

In a URL path, a space must be written %20. In HTML form submissions and query strings produced by the older form encoding (application/x-www-form-urlencoded), a space is written as a plus sign instead. URLSearchParams follows that form convention.

Most servers decode + as a space in the query string, but not in the path. If you are unsure, %20 is the safe choice in a URL. If you are reading values back, make sure you use the decoder that matches how the text was produced. A real plus sign that is part of your data must be written %2B, otherwise it may come back as a space.

Double encoding and other common mistakes

  • Encoding a whole URL with the component function. Running encodeURIComponent on https://example.com/page produces text where the colon and slashes are escaped, and it no longer works as a link. Encode the pieces, then assemble the URL.
  • Encoding twice. If text has already been encoded and you encode it again, the percent signs themselves become %25, so %20 turns into %2520. Seeing %25 in a URL is usually a sign of this. Decode once and compare.
  • Decoding too early. If you decode a full query string first and split it into parameters afterwards, an encoded & inside a value becomes a real separator. Split first, then decode each value.
  • Forgetting about non-ASCII text. Some old systems assumed another character encoding than UTF-8. If decoded text shows odd symbols, a mismatch of encodings is the likely reason.
  • Treating encoding as security. Percent-encoding only protects the structure of a URL. It does not hide data, since anyone can decode it. For the same point about another format, see Base64 is not encryption.

Quick checklist

  • Encode each value separately, then join the parts with the real separators.
  • Use encodeURIComponent for values and avoid it on whole URLs.
  • Expect non-ASCII characters to become several %XX groups.
  • Remember + means space only in form-style query strings.
  • If you see %25, check for double encoding.
  • Decode exactly once, after splitting the query into parameters.

The URL encoder and decoder converts text in both directions, which helps when you are debugging a link that looks garbled. If the data you are handling is a binary blob or a token rather than a URL piece, the Base64 encoder and decoder is the better fit, and the JSON formatter helps when the decoded value turns out to be a JSON document.

Sources