# URL encoding explained: why a space becomes %20, which characters need it, and the encodeURI vs encodeURIComponent trap

> What does %20 mean in a link? Which characters are safe in a URL and which are not, how Hindi and accented letters are encoded, why an ampersand can silently split your parameter, and what double encoding (%2520) looks like. With a reference table and real examples.

Published 2026-10-22 by Toolcloak. 4 minute read. Original: https://toolcloak.com/articles/url-encoding-explained-why-a-space-becomes-20-percent-encoded-characters-and-the-encodeuri-vs-encodeuricomponent-trap
Related free tool: [URL Encoder](https://toolcloak.com/tools/url-encoder)

A web address can only safely carry a small set of plain characters. Everything else, from a space to a Hindi letter to an ampersand, has to be written as a **percent sign followed by two hexadecimal digits**. That is URL encoding, and it is why you see `%20` in links. Getting it wrong gives broken links, missing parameters and pages that open fine on your laptop and fail for everyone else.

> **In short**
> - **A space is `%20`.** In form data and many query strings you will also see `+` for a space.
> - **Letters, digits and `- _ . ~` never need encoding.** Everything else, including `&`, `=`, `?`, `#` and non-English letters, may.
> - **Encode each value on its own,** before you put it into a URL. Use `encodeURIComponent` for values, not `encodeURI`.
> - **Encode once only.** `%2520` is a sign that something was encoded twice.

## How percent encoding works

Each character is turned into its bytes in UTF-8, and each byte is written as `%` plus two hex digits. A space is the single byte 32, which is hex 20, so it becomes `%20`. The letter é takes two bytes (C3 and A9), so it becomes `%C3%A9`.

**Same idea, different lengths**

|  | Value | Note |
| --- | --- | --- |
| A space | %20 | 1 byte |
| The letter é | %C3%A9 | 2 bytes |
| The Hindi word नमस्ते | 18 codes | 6 characters × 3 bytes |
| Its encoded length | 54 chars | %E0%A4%A8%E0%A4%AE…  |

*Each Devanagari letter is three bytes in UTF-8, so a six-character word becomes eighteen percent codes. Browsers show the readable word but send the encoded form.*

Try it: [URL Encoder](https://toolcloak.com/tools/url-encoder). Paste text or a link and encode it, or paste a %-encoded string and decode it back to readable text.

## The four kinds of character

**What needs encoding and what does not**

| Box | What it means |
| --- | --- |
| Unreserved: safe | A–Z, a–z, 0–9 and the four marks `- _ . ~`. Never need encoding. |
| Reserved: have a job | `: / ? # [ ] @ ! $ & ' ( ) * + , ; =` mark parts of the URL. Encode them when they are part of your data. |
| Unsafe: always encode | Space, quotes, `< > { } | \ ^ %` and control characters. |
| Non-English: encode as UTF-8 | Hindi, Tamil, Arabic, accented letters, emoji and symbols. |

*A reserved character is fine when it does its normal job. The `?` that starts the query is fine. A `?` inside a search term is not.*

## Reference table

| Character | Encoded | Why it matters |
| --- | --- | --- |
| space | %20 | Breaks the link if left as it is |
| & | %26 | Otherwise starts a new parameter |
| = | %3D | Otherwise splits key from value |
| ? | %3F | Otherwise starts the query string |
| # | %23 | Otherwise starts the fragment, and the rest is lost |
| + | %2B | Otherwise may be read as a space |
| / | %2F | Otherwise adds a path level |
| , | %2C | Safe in most places, encoded in values |
| % | %25 | The escape character itself |
| @ | %40 | Otherwise read as a user marker |

*A good habit is to encode every value that came from a person or a database. Never assume it contains only letters and numbers.*

## The ampersand that split a parameter

Suppose you build a search link for “rock & roll”. Dropped in unencoded, the ampersand ends the parameter, and ` roll` becomes a stray key with no value.

**Searching for “rock & roll”**

| Not encoded | Encoded |
| --- | --- |
| Broken | Works |
| `?q=rock & roll` | `?q=rock%20%26%20roll` |
| Reads as q=“rock ” and a second key “ roll” | One parameter: q=“rock & roll” |
| The search gets only half the words | The server gets the whole phrase |

*The same problem appears with `=`, `#` and `+`. It also affects WhatsApp links and campaign tags. See the [WhatsApp link guide](https://toolcloak.com/articles/how-to-make-a-whatsapp-link-that-opens-a-chat-with-a-ready-message-no-need-to-save-the-number) and [UTM naming rules](https://toolcloak.com/articles/utm-parameters-explained-source-medium-campaign-and-naming-rules-that-keep-reports-clean).*

## encodeURI against encodeURIComponent

JavaScript has two functions and they do different jobs. **`encodeURI`** is for a whole URL, so it leaves characters such as `:`, `/`, `?`, `&` and `=` alone. **`encodeURIComponent`** is for a single value, so it encodes all of those. Using the first on a value is a very common bug.

| Input | encodeURI | encodeURIComponent |
| --- | --- | --- |
| a b&c=d | a%20b&c=d | a%20b%26c%3Dd |
| café | caf%C3%A9 | caf%C3%A9 |
| 100% नकद | 100%25%20%E0%A4%A8%E0%A4%95%E0%A4%A6 | 100%25%20%E0%A4%A8%E0%A4%95%E0%A4%A6 |
| https://x.com/a b?q=1 | https://x.com/a%20b?q=1 | https%3A%2F%2Fx.com%2Fa%20b%3Fq%3D1 |

*Rule of thumb: build the URL from parts, and run `encodeURIComponent` on each value. Use `encodeURI` only on a complete address you want to keep intact.*

## Double encoding

If you encode a string that is already encoded, the `%` itself becomes `%25`, and `%20` turns into `%2520`. The server decodes once and sees the text `%20` instead of a space. It is a sign that two layers each tried to be helpful.

**“a b” encoded twice**

1. **Original.** `a b`
2. **Encode once.** `a%20b`. This is correct.
3. **Encode again.** `a%2520b`. The % became %25.
4. **Server decodes once.** `a%20b`. The user sees a stray %20 on the page.

*If a link shows %20 in the page text, look for the step that encoded it a second time, then remove one.*

## Plus or %20?

Inside a query string, many systems treat `+` as a space. That is the older **form encoding** style, and it is what HTML forms and the `URLSearchParams` object produce. In the path of a URL, `+` means a literal plus sign, and a space must be `%20`. When in doubt use `%20`, which works in both places.

> **Encoding is not security:** Percent encoding only makes characters safe to carry in a URL. It does not hide anything. A password or token in a link is still readable by anyone who sees it, and the [Base64 guide](https://toolcloak.com/articles/base64-is-not-encryption-and-it-makes-files-a-third-bigger) explains why scrambling text is not encryption.

## A practical checklist

1. Encode each value separately, then join with `?`, `&` and `=`.
2. Encode non-English text as UTF-8. Any modern tool does this.
3. Keep slashes in the path, and encode them only when they are part of a name.
4. Decode once when you read a value back. Do not decode twice.
5. Test the finished link in a private window and by reading the address bar.

Going the other way? The [URL Decoder](https://toolcloak.com/tools/url-decoder) turns %20-style text back into words.

## Frequently asked questions

### What does %20 mean in a URL?

%20 is a space. URLs cannot contain a raw space, so it is written as a percent sign and the hexadecimal code for the space character, which is 20.

### How do I encode a URL?

Use a URL encoder, or in JavaScript call encodeURIComponent on each value before adding it to the link. It turns spaces, ampersands and non-English letters into percent codes.

### What is the difference between encodeURI and encodeURIComponent?

encodeURI is for a full URL and leaves characters like : / ? & = alone. encodeURIComponent is for a single value and encodes those too. Use it for query values.

### How are Hindi letters encoded in a URL?

Each letter is converted to its UTF-8 bytes and each byte is written as %XX. A Devanagari letter is three bytes, so one letter becomes three percent codes.

### Why is there a %25 in my URL?

%25 is an encoded percent sign. If you see %2520 where you expected %20, the text was encoded twice.

### Is + the same as %20?

In a query string, often yes, because forms use + for a space. In the path part of a URL, + is a literal plus sign. %20 is the safe choice everywhere.

### Which characters are safe in a URL?

Letters A to Z and a to z, digits 0 to 9, and the marks - _ . ~ are always safe. Everything else may need to be encoded depending on where it appears.

