In short
HTML URL encoding (percent-encoding) turns spaces and special characters into safe codes like %20, so links and form data travel correctly across the web. You saw in the style guide lesson that a space in a file name becomes %20.
HTML URL encoding (percent-encoding) turns spaces and special characters into safe codes like %20, so links and form data travel correctly across the web.
You saw in the style guide lesson that a space in a file name becomes %20. In this lesson you will learn why that happens, which characters need encoding, and how browsers encode form data for you.
The parts of a URL
A URL (Uniform Resource Locator) is the address of something on the web. Let's take one apart:
https://shop.example.com:443/products/garden-chairs?color=green&page=2#reviews
| Part | In the example | What it means |
|---|---|---|
| Scheme | https | The protocol: how to talk to the server |
| Host | shop.example.com | The server's name |
| Port | 443 | The "door" on the server (usually hidden, because 443 is the default for HTTPS) |
| Path | /products/garden-chairs | Which page or file on the server |
| Query string | ?color=green&page=2 | Extra data as name=value pairs, joined with & |
| Fragment | #reviews | A spot inside the page (an element with id="reviews") |
Notice that some characters have a special job: : and / separate parts, ? starts the query, & and = split the pairs, and # starts the fragment.
Why do URLs need encoding?
URLs may only contain a small set of safe characters: the letters A to Z and a to z, the digits 0 to 9, and -, _, . and ~. Everything else is a problem:
- Characters with a special job. Imagine a search for "Tom & Jerry". If you write
?q=Tom & Jerry, the&looks like the start of a new pair, so the server receives onlyTom. - Spaces. A space ends a URL in many places, such as emails and chat messages, so the rest of the link is lost.
- Non-English letters. Letters like é or ü and characters like 東 are not allowed directly in the raw URL.
URL encoding, also called percent-encoding, solves this. It replaces each unsafe character with a % sign followed by two hexadecimal digits (0 to 9 and A to F) that give the byte's value. It is like writing a phone number in words when the form only accepts digits: the meaning stays, only the format changes.
Percent-encoding table of common characters
| Character | Encoded | Character | Encoded |
|---|---|---|---|
| space | %20 (or + in form data) | / | %2F |
! | %21 | : | %3A |
" | %22 | ; | %3B |
# | %23 | = | %3D |
$ | %24 | ? | %3F |
% | %25 | @ | %40 |
& | %26 | é | %C3%A9 |
' | %27 | ü | %C3%BC |
+ | %2B | € | %E2%82%AC |
, | %2C | 😀 | %F0%9F%98%80 |
Look at the last rows. Non-English characters are first turned into their UTF-8 bytes (from the previous lesson), and then each byte is percent-encoded. That is why é (2 bytes in UTF-8) becomes two codes, and the emoji (4 bytes) becomes four.
Note: You can type
caféin the address bar and the browser shows it nicely, but behind the scenes it sendscaf%C3%A9. Copy the address and paste it in a text editor to see the encoded form.
Spaces: %20 or +?
You will see spaces encoded in two ways:
%20is the standard encoding and works everywhere in a URL, including the path:/files/annual%20report.pdf.+means a space only in the query string of form data:?q=garden+chairs. In a path, a+is just a plus sign.
Because + can mean a space, a real plus sign in form data must be encoded as %2B. Searching for "C++" sends q=C%2B%2B.
How HTML forms encode data
When a form is sent, the browser encodes the data for you. Here is a search form:
<form action="/search" method="get">
<label for="q">Search products</label>
<input type="search" id="q" name="q">
<select name="category">
<option value="home & garden">Home and garden</option>
<option value="toys">Toys</option>
</select>
<button type="submit">Search</button>
</form>
If you type red chairs & tables and pick the first category, the browser goes to:
/search?q=red+chairs+%26+tables&category=home+%26+garden
With method="get", the data goes into the URL like this. Each field becomes name=value, the pairs are joined with &, spaces become +, and the & inside the text becomes %26 so it can't be confused with the separator. This format is called application/x-www-form-urlencoded, and it is the default for forms.
With method="post", the same encoded text is sent in the body of the request instead of the URL. To upload files, you change the encoding with the enctype attribute:
<form action="/upload.php" method="post" enctype="multipart/form-data">
<label for="photo">Profile photo</label>
<input type="file" id="photo" name="photo" accept="image/*">
<button type="submit">Upload</button>
</form>
multipart/form-data sends each field as a separate part, which can hold binary data such as images. You need it for every form with <input type="file">.
Common mistake: Writing an
&directly inside anhrefwith spaces or special text, like<a href="/search?q=salt & pepper">. The link breaks at the space and the&. Write<a href="/search?q=salt%20%26%20pepper">instead.
Encoding URLs in links and with JavaScript
When you write links by hand, encode any unsafe characters yourself:
<!-- A file name with a space -->
<a href="docs/price%20list%202026.pdf">Download the price list (PDF)</a>
<!-- A search link with special characters -->
<a href="https://www.example.com/search?q=fish%20%26%20chips">Find fish & chips shops</a>
<!-- A pre-filled email: subject and body are encoded too -->
<a href="mailto:hello@example.com?subject=Order%20%231042&body=Hi%2C%20I%20have%20a%20question.">Email us about your order</a>
The first link opens a PDF whose real name contains spaces. The second sends a search for "fish & chips". The third opens the email program with the subject "Order #1042" already filled in. Notice that the # is encoded as %23, or the browser would treat it as a fragment. The best fix for the first one is still to rename the file price-list-2026.pdf.
When JavaScript builds a URL, it uses the built-in function encodeURIComponent(), which encodes one value for you:
const url = `/search?q=${encodeURIComponent("Tom & Jerry")}`; // Output: /search?q=Tom%20%26%20Jerry
This one line takes the user's text, encodes the space and the &, and puts the safe result into the URL. You will use this a lot in the JavaScript course. To learn more, see MDN: encodeURIComponent().
Practice exercise
Build a small page with three links: one to a file called summer menu.pdf, one that searches https://www.example.com/search for 100% cotton t-shirts, and one mailto: link with the subject Question about "Blue" sofa. Encode every link by hand using the table above, then hover over each link and check the address shown in the bottom corner of the browser.
Hint: You need %20 for spaces, %25 for the percent sign and %22 for the double quotes.
Key takeaways
- A URL has a scheme, host, port, path, query string and fragment, and some characters have special jobs in it.
- Percent-encoding replaces unsafe characters with
%and two hex digits, using the UTF-8 bytes for non-English letters. - A space is
%20anywhere, or+in form query strings; a real+must be%2B. - Forms encode data automatically:
application/x-www-form-urlencodedby default,multipart/form-datafor file uploads. - In JavaScript,
encodeURIComponent()encodes a value in one line.