# URL Encoder and Decoder

> URL encode and decode text online as you type, choose %20 or + for spaces, split any URL into editable query parameters and strip UTM tags in one click.

URL: https://acrafto.com/en/url-encoder-decoder/  
Updated: 2026-10-03

Tools are interactive browser apps; there is no public API, no endpoints to call and no server-side processing. To use a tool, open its HTML page in a browser.

URL encode and decode text online as you type: the tool turns spaces, accented letters and symbols such as `&` or `?` into percent-encoded sequences like `%20`, and turns them back into readable text. The second tab is a URL parser. It splits any address into protocol, host, path and query parameters that you can edit, switch off or strip of tracking tags, and writes the correctly encoded URL back for you. Everything happens in your browser.

## How to URL encode and decode text

1. Type or paste into the field on the **Encode / Decode** tab. The **Result** updates with every keystroke.
2. Pick the **Direction**. **Encode** makes text safe for a URL, **Decode** turns `caf%C3%A9%20au%20lait` back into `café au lait`. Paste text with sequences like `%20` into the empty field and the tool switches to **Decode** by itself (**Encode it instead** switches back). Plain text that needs encoding, pasted in **Decode** mode, switches it to **Encode** the same way, with **Decode it instead**.
3. When encoding, choose under **Encode as** what the text is (see the next section). The default, **Parameter value**, is right for a single query value.
4. **Copy** puts the result on the clipboard. **Swap** moves the result into the input and flips the direction. That is a quick round trip check: decoding what you just encoded must give your original text back.

Every character the tool changed is highlighted in the result. Hover over one to see the character, its Unicode code point and its bytes, for example `é U+00E9 %C3%A9`. Below the fields you see the number of **Characters**, **UTF-8 bytes** and **Encoded characters** (or **Decoded characters**). **Try an example** loads the sentence `Price: 50% off, café & crème brûlée? Yes!`, which has 41 characters but 45 UTF-8 bytes, because each accented letter takes two bytes.

When encoding, **Each line separately** encodes every line on its own and keeps the line breaks, which suits a list of values or links. Without it, a line break is encoded too and becomes `%0A`. When the text is a URL with parameters, the tool offers **Split it into parts**, which opens the address in the parser tab.

## Encode a URL parameter, a whole URL or form data

Not every character has to be encoded everywhere. A slash separates folders in a path but is plain data inside a parameter value, so the right result depends on what you encode. **Encode as** offers four modes:

- **Parameter value** works like JavaScript’s `encodeURIComponent` and suits one query value or path segment. It encodes everything except letters, digits and `- _ . ! ~ * ' ( )`, so an `&`, `=`, `/` or `?` inside the value cannot break the URL. Encoding `café & crème` gives `caf%C3%A9%20%26%20cr%C3%A8me`, ready to go after `q=`.
- **Whole URL** is for a complete address that only needs cleaning up. It encodes spaces, non-ASCII characters, control characters, the backtick and `" < > \ ^ { | }`, and keeps everything that gives a URL its structure: `: / ? # [ ] @ ! $ & ' ( ) * + , ; =`. So `https://example.com/search?q=café au lait&lang=fr` becomes `https://example.com/search?q=caf%C3%A9%20au%20lait&lang=fr`. Sequences that are already encoded stay as they are, and a lone `%` becomes `%25`. This is where it differs from JavaScript’s `encodeURI`, which turns an existing `%20` into `%2520` and encodes the brackets of an IPv6 address such as `http://[2001:db8::1]:8080/`.
- **Form data** follows the [application/x-www-form-urlencoded](https://url.spec.whatwg.org/#application/x-www-form-urlencoded) format that HTML forms and `URLSearchParams` produce. A space becomes `+`, and only letters, digits and `* - . _` stay unencoded, so `! ' ( ) ~` are encoded as well.
- **Strict RFC 3986** leaves only the unreserved characters of [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986) unencoded: letters, digits and `- . _ ~`. OAuth 1.0 (RFC 5849) and AWS Signature Version 4 require exactly this form, because a signature only matches when both sides encode `!` or `*` the same way.

The same characters in each mode:

| Character | Parameter value | Whole URL | Form data | Strict RFC 3986 |
| --- | --- | --- | --- | --- |
| space | `%20` | `%20` | `+` | `%20` |
| `&` | `%26` | `&` | `%26` | `%26` |
| `/` | `%2F` | `/` | `%2F` | `%2F` |
| `+` | `%2B` | `+` | `%2B` | `%2B` |
| `~` | `~` | `~` | `%7E` | `~` |
| `!` | `!` | `!` | `%21` | `%21` |
| `*` | `*` | `*` | `*` | `%2A` |
| `é` | `%C3%A9` | `%C3%A9` | `%C3%A9` | `%C3%A9` |

Text is always encoded as UTF-8 and the hex digits are always uppercase. If the input already contains sequences like `%20`, a note says so and offers **Decode it instead**, so you do not encode the text twice by mistake.

To pass JSON in a query parameter, minify it in the [JSON formatter](https://acrafto.com/en/json-formatter-validator/) and encode it as **Parameter value**: `{"id":7,"tags":["a","b"]}` becomes `%7B%22id%22%3A7%2C%22tags%22%3A%5B%22a%22%2C%22b%22%5D%7D`. It works the other way round too: decode the parameter here, then format it there.

## URL decode problems: plus signs, %2520 and broken sequences

Decoding usually just works, but four situations trip people up. The tool handles each of them instead of stopping with an error:

- A plus sign stands for a space in form data and most query strings. **Decode + as a space** is on by default, so `caf%C3%A9+au+lait` decodes to `café au lait`. In a whole URL only the plus signs after the `?` count as spaces, because in a path a plus is an ordinary character. Switch the option off when a plus sign is meant literally. A plus that was encoded as `%2B` always stays a plus sign.
- Double encoding happens when two layers of code each encode the same value, which RFC 3986 explicitly warns against. Each `%` becomes `%25`, so a space turns from `%20` into `%2520`. If the decoded result still contains sequences like `%20`, the tool says the text was probably encoded twice and offers **Decode again**.
- An invalid sequence, a `%` that is not followed by two hex digits as in `100%` or `%G1`, makes JavaScript’s `decodeURIComponent` throw a URIError. Here such sequences are left as they are, marked in red and counted, and the rest of the text is decoded.
- Old Latin-1 links come from the time before UTF-8, when some sites encoded `é` as the single byte `%E9`. `caf%E9` is not valid UTF-8, so `decodeURIComponent` fails and Python’s `unquote` returns `caf` followed by the replacement character U+FFFD. The tool reads such bytes as Windows-1252, decodes `caf%E9` to `café` and adds a note saying so.

Control characters in decoded text, such as a tab or a null byte, are shown as visible symbols like ␉ and ␀, but **Copy** copies the real text.

## URL parser: split a URL and edit its query parameters

Paste an address into the **URL** field on the **Parse & edit URL** tab and it is split into **Protocol**, **Host**, **Port**, **Path** and **Fragment**, plus **Username** and **Password** when the URL contains them. The values are shown decoded, so the tab is also the quickest way to decode URL parameters: you read `running shoes` instead of `running+shoes`. Editing works both ways, like the URL bar and the parameter table in Postman. Change a field and the URL is rewritten at once, correctly encoded; change the URL and all parts are read again. Parts you do not touch stay exactly as they were, character for character.

The **Query parameters** table lists every parameter with its **Name** and **Value**. Untick **Include in the URL** to leave a parameter out without deleting it, which helps when you are looking for the one parameter that breaks a request. **Add parameter**, **Remove parameter** and **Sort A to Z** do what they say. Repeated names like `tag=a&tag=b` and names without a value like `?debug` are kept. **Spaces in parameters** decides whether spaces are written as `%20` or `+`; by default it follows the URL you pasted.

Login and payment links often carry a second URL inside a parameter, encoded so that its own `?` and `&` do not mix with the outer ones:

`https://auth.example.com/authorize?client_id=abc&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback%3Ftab%3D2`

A value that is itself a URL, typically in `redirect_uri`, `return`, `url` or `next`, gets an **Edit the URL inside** button. The inner address `https://app.example.com/callback?tab=2` opens as its own level with its own parts and parameters, a breadcrumb (**Main URL** › redirect\_uri) leads back, and every change is encoded back into the outer URL. **Copy main URL** copies the result. This works several levels deep.

When the part after `#` looks like parameters, as in `#access_token=...&state=...` in the OAuth implicit flow or `#/search?q=shoes` in the routes of single page apps, a second table, **Fragment parameters**, lists them too.

The parser also points out problems: a URL without a protocol, which browsers treat as a relative link; a port outside 0 to 65535; and characters that must be encoded, such as spaces, accented letters, `"` or `<`, which **Encode them** fixes in one step. Text without an address, like `a=1&b=2`, is read as a query string. For an [internationalized domain name](https://en.wikipedia.org/wiki/Internationalized_domain_name) the tool shows the Punycode form that DNS and browsers use, so `münchen.de` becomes `xn--mnchen-3ya.de`, and a domain starting with `xn--` gets its readable form.

**Copy URL** copies the finished address, **Open** opens it in a new tab (http and https links only), and **Copy as JSON** gives you the parameters as a JSON object, with repeated names collected into an array.

## Remove UTM and other tracking parameters from a URL

Links from newsletters, ads and social networks carry parameters that only tell the site where the visitor came from. The [UTM parameters](https://en.wikipedia.org/wiki/UTM_parameters) `utm_source`, `utm_medium`, `utm_campaign`, `utm_term` and `utm_content` go back to Urchin, the predecessor of Google Analytics. Click IDs such as `fbclid` (Facebook), `gclid` (Google Ads) and `msclkid` (Microsoft Advertising) are appended by the platforms themselves.

The parser marks these with a **tracking** tag, and **Remove tracking (n)** deletes all of them at once. Besides any `utm_*` parameter it recognizes more than 20 others, such as `ttclid` (TikTok), `mc_cid` (Mailchimp) and `_hsenc` (HubSpot). Parameters the page needs stay in place: in the shop link from **Try an example**, **Remove tracking (4)** removes `utm_source`, `utm_medium`, `utm_campaign` and `fbclid` and keeps `q`, `size`, `return` and the `#reviews` fragment.

A link that is going into a [QR code](https://acrafto.com/en/free-online-qr-code-generator/) is worth cleaning up here first. Without tracking parameters it is shorter, and a shorter link gives a less dense code that is easier to scan.

## What percent encoding is and how characters become %XX

[Percent-encoding](https://en.wikipedia.org/wiki/Percent-encoding), also called URL encoding, writes a character as `%` followed by two hexadecimal digits. A URL may only contain a limited set of ASCII characters, and some of them have a job: `?` starts the query, `&` separates parameters, `#` starts the fragment. RFC 3986 calls these reserved characters (`: / ? # [ ] @` and `! $ & ' ( ) * + , ; =`). Letters, digits and `- . _ ~` are unreserved and never need encoding. Everything else, and every reserved character used as plain data, gets encoded.

Characters outside ASCII are first turned into UTF-8 bytes, and each byte gets its own `%XX`:

- `é` is U+00E9, which UTF-8 stores as the two bytes C3 A9, so it becomes `%C3%A9`.
- `€` is U+20AC, three bytes: `%E2%82%AC`.
- An emoji such as U+1F600 (grinning face) takes four bytes: `%F0%9F%98%80`.

`%c3%a9` and `%C3%A9` mean the same, but RFC 3986 recommends uppercase, which is what the tool writes. A percent encoding table of the characters you meet most often:

| Character | Encoded | Character | Encoded |
| --- | --- | --- | --- |
| space | `%20` | `+` | `%2B` |
| `!` | `%21` | `,` | `%2C` |
| `"` | `%22` | `/` | `%2F` |
| `#` | `%23` | `:` | `%3A` |
| `$` | `%24` | `;` | `%3B` |
| `%` | `%25` | `=` | `%3D` |
| `&` | `%26` | `?` | `%3F` |
| `'` | `%27` | `@` | `%40` |
| `(` | `%28` | `[` | `%5B` |
| `)` | `%29` | `]` | `%5D` |
| `*` | `%2A` | line break | `%0A` |

## URL encoding in JavaScript, Python and PHP

Every language has functions for this, and they differ mainly in how they treat spaces, slashes and `! ' ( ) * ~`.

JavaScript has [`encodeURIComponent`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) for a value, `encodeURI` for a whole address and `URLSearchParams` for form encoding:

```
encodeURIComponent("café & crème")                     // "caf%C3%A9%20%26%20cr%C3%A8me"
encodeURI("https://example.com/a b?q=café")            // "https://example.com/a%20b?q=caf%C3%A9"
new URLSearchParams({ q: "café & crème" }).toString()  // "q=caf%C3%A9+%26+cr%C3%A8me"
decodeURIComponent("caf%C3%A9")                        // "café"
```

`decodeURIComponent` does not turn `+` into a space, and it throws a URIError on an invalid sequence such as `100%`.

In Python the functions live in `urllib.parse`. `quote` keeps `/` by default (`safe='/'`) and otherwise encodes everything except the RFC 3986 unreserved characters. `quote_plus` writes spaces as `+` and encodes `/` too:

```
from urllib.parse import quote, quote_plus, urlencode, unquote_plus

quote("café & crème/brûlée")       # 'caf%C3%A9%20%26%20cr%C3%A8me/br%C3%BBl%C3%A9e'
quote("a b/c", safe="")            # 'a%20b%2Fc'
quote_plus("café & crème/brûlée")  # 'caf%C3%A9+%26+cr%C3%A8me%2Fbr%C3%BBl%C3%A9e'
urlencode({"q": "café & crème", "page": 2})  # 'q=caf%C3%A9+%26+cr%C3%A8me&page=2'
unquote_plus("caf%C3%A9+au+lait")  # 'café au lait'
```

In PHP, `urlencode` encodes the way an HTML form does and writes a space as `+`, while `rawurlencode` follows RFC 3986 and writes `%20`:

```
urlencode("café & crème");     // "caf%C3%A9+%26+cr%C3%A8me"
rawurlencode("café & crème");  // "caf%C3%A9%20%26%20cr%C3%A8me"
```

`rawurlencode` gives the same result as **Strict RFC 3986**. `urlencode` matches **Form data** except for `*`, which it encodes as `%2A`.

## Frequently asked questions

### Should a space be encoded as %20 or +?

`%20` works everywhere in a URL. A `+` means a space only in the query string and in form data, the format HTML forms send. In a path, `+` is an ordinary plus sign, so `/a+b` stays `/a+b`. When a query value needs a real plus sign, write it as `%2B`. In the tool, **Form data** writes spaces as `+` and the other three modes as `%20`.

### What do %20, %2F and %3D mean in a URL?

They are encoded characters: `%20` is a space, `%2F` a slash and `%3D` an equals sign. Others you see often are `%26` (&), `%3F` (?), `%3A` (:), `%2C` (comma) and `%27` (apostrophe). The two digits are the character's code in hexadecimal. Accented letters and other non-ASCII characters take two to four such pairs, like `%C3%A9` for é. Paste the whole string into the decoder to read it.

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

`encodeURI` is meant for a whole address and leaves the characters that structure it, such as `: / ? # & =`, alone. `encodeURIComponent` is meant for one part, a parameter value or a path segment, and encodes those characters too, so `https://example.com/?a=1&b=2` becomes `https%3A%2F%2Fexample.com%2F%3Fa%3D1%26b%3D2`. In this tool, **Parameter value** matches `encodeURIComponent`, and **Whole URL** is like `encodeURI` but keeps existing sequences such as `%20` instead of turning them into `%2520`.

### How do I remove UTM parameters from a URL?

Paste the link into the **Parse & edit URL** tab and press **Remove tracking (n)**. It deletes every `utm_*` tag and click IDs like `fbclid` and `gclid` at once. Then press **Copy URL**. To drop only some of them, use **Remove parameter** on the rows you do not want.

### Is URL encoding the same as encryption or Base64?

No. URL encoding hides nothing: anyone can decode `caf%C3%A9` back to café, so it never protects a password or a token. It only makes characters safe to use in an address. Base64 is a different encoding that turns any data, including binary files, into a string of 64 characters. A Base64 string in a URL still needs its `+`, `/` and `=` encoded, unless you use the URL safe variant, which the [Base64 encoder and decoder](https://acrafto.com/en/base64-encoder-decoder/) can produce.

### Are the URLs I paste uploaded or stored?

No. Encoding, decoding and parsing run in your browser, and nothing you paste is sent to a server. That matters, because URLs often carry access tokens, session IDs or password reset codes. The browser remembers only your chosen tab and options, never the texts. The only thing that loads the address is **Open**, which opens it in a new tab just like clicking the link would.

More tools for programmers are in the [Developers](https://acrafto.com/en/developers/) category, and tools that turn one format into another are collected under [Converters](https://acrafto.com/en/converters/). To find what differs between two long URLs, for example a working and a failing API call, paste them into the [text compare tool](https://acrafto.com/en/compare-text-diff-checker/) and compare by characters.

## Other languages

- Čeština (cs): [URL encode a decode](https://acrafto.com/cs/url-encode-decode/) ([Markdown](https://acrafto.com/cs/url-encode-decode/index.md))
- Slovenčina (sk): [URL encoder a decoder](https://acrafto.com/sk/url-encode-decode-online/) ([Markdown](https://acrafto.com/sk/url-encode-decode-online/index.md))
- Deutsch (de): [URL Encoder und Decoder](https://acrafto.com/de/url-encoder-decoder-online/) ([Markdown](https://acrafto.com/de/url-encoder-decoder-online/index.md))
- Français (fr): [Encodeur et décodeur d'URL](https://acrafto.com/fr/encodeur-decodeur-url/) ([Markdown](https://acrafto.com/fr/encodeur-decodeur-url/index.md))
- Español (es): [Codificador y decodificador de URL](https://acrafto.com/es/codificar-decodificar-url-online/) ([Markdown](https://acrafto.com/es/codificar-decodificar-url-online/index.md))
- Italiano (it): [URL encoder e decoder](https://acrafto.com/it/url-encode-decode-online/) ([Markdown](https://acrafto.com/it/url-encode-decode-online/index.md))
- Português (pt): [Codificador e decodificador de URL](https://acrafto.com/pt/codificar-decodificar-url-online/) ([Markdown](https://acrafto.com/pt/codificar-decodificar-url-online/index.md))
- Nederlands (nl): [URL encoder en decoder](https://acrafto.com/nl/url-encoder-decoder/) ([Markdown](https://acrafto.com/nl/url-encoder-decoder/index.md))
- Polski (pl): [Kodowanie i dekodowanie URL](https://acrafto.com/pl/url-encode-decode-online/) ([Markdown](https://acrafto.com/pl/url-encode-decode-online/index.md))
- Română (ro): [URL encoder și decoder](https://acrafto.com/ro/url-encode-decode-online/) ([Markdown](https://acrafto.com/ro/url-encode-decode-online/index.md))
- Magyar (hu): [URL kódoló és dekódoló](https://acrafto.com/hu/url-kodolas-dekodolas/) ([Markdown](https://acrafto.com/hu/url-kodolas-dekodolas/index.md))
- Ελληνικά (el): [Κωδικοποίηση και αποκωδικοποίηση URL](https://acrafto.com/el/url-encode-decode-online/) ([Markdown](https://acrafto.com/el/url-encode-decode-online/index.md))
- Български (bg): [URL encode и decode](https://acrafto.com/bg/url-encode-decode-onlain/) ([Markdown](https://acrafto.com/bg/url-encode-decode-onlain/index.md))
- Hrvatski (hr): [URL koder i dekoder](https://acrafto.com/hr/url-encode-decode-online/) ([Markdown](https://acrafto.com/hr/url-encode-decode-online/index.md))
- Slovenščina (sl): [URL kodirnik in dekodirnik](https://acrafto.com/sl/url-kodirnik-dekodirnik/) ([Markdown](https://acrafto.com/sl/url-kodirnik-dekodirnik/index.md))
- Eesti (et): [URL kodeerija ja dekodeerija](https://acrafto.com/et/url-kodeerija-dekodeerija/) ([Markdown](https://acrafto.com/et/url-kodeerija-dekodeerija/index.md))
- Latviešu (lv): [URL kodētājs un dekodētājs](https://acrafto.com/lv/url-kodetajs-dekodetajs/) ([Markdown](https://acrafto.com/lv/url-kodetajs-dekodetajs/index.md))
- Lietuvių (lt): [URL koduotuvas ir dekoduotuvas](https://acrafto.com/lt/url-koduotuvas-dekoduotuvas/) ([Markdown](https://acrafto.com/lt/url-koduotuvas-dekoduotuvas/index.md))
- Svenska (sv): [URL-kodare och avkodare](https://acrafto.com/sv/url-kodare-avkodare/) ([Markdown](https://acrafto.com/sv/url-kodare-avkodare/index.md))
- Dansk (da): [URL encoder og dekoder](https://acrafto.com/da/url-encoder-dekoder-online/) ([Markdown](https://acrafto.com/da/url-encoder-dekoder-online/index.md))
- Suomi (fi): [URL-kooderi ja -dekooderi](https://acrafto.com/fi/url-encode-decode-kooderi/) ([Markdown](https://acrafto.com/fi/url-encode-decode-kooderi/index.md))
- Norsk (no): [URL-enkoder og -dekoder](https://acrafto.com/no/url-enkoder-dekoder/) ([Markdown](https://acrafto.com/no/url-enkoder-dekoder/index.md))
- Українська (uk): [Кодування й декодування URL](https://acrafto.com/uk/url-encode-decode-onlain/) ([Markdown](https://acrafto.com/uk/url-encode-decode-onlain/index.md))
- Русский (ru): [URL кодировщик и декодировщик](https://acrafto.com/ru/url-koder-dekoder/) ([Markdown](https://acrafto.com/ru/url-koder-dekoder/index.md))
- Српски (sr): [URL enkoder i dekoder](https://acrafto.com/sr/url-enkoder-dekoder/) ([Markdown](https://acrafto.com/sr/url-enkoder-dekoder/index.md))
- Македонски (mk): [URL енкодер и декодер](https://acrafto.com/mk/url-encode-decode-onlajn/) ([Markdown](https://acrafto.com/mk/url-encode-decode-onlajn/index.md))
- Bosanski (bs): [URL koder i dekoder](https://acrafto.com/bs/url-encode-decode/) ([Markdown](https://acrafto.com/bs/url-encode-decode/index.md))
- Shqip (sq): [URL Encoder dhe Decoder](https://acrafto.com/sq/url-encode-decode-online/) ([Markdown](https://acrafto.com/sq/url-encode-decode-online/index.md))
- Türkçe (tr): [URL kodlayıcı ve çözücü](https://acrafto.com/tr/url-encode-decode/) ([Markdown](https://acrafto.com/tr/url-encode-decode/index.md))
- 日本語 (ja): [URLエンコード・デコード](https://acrafto.com/ja/url-encode-decode/) ([Markdown](https://acrafto.com/ja/url-encode-decode/index.md))
- 한국어 (ko): [URL 인코딩 디코딩](https://acrafto.com/ko/url-inkoding-dikoding/) ([Markdown](https://acrafto.com/ko/url-inkoding-dikoding/index.md))
- العربية (ar): [ترميز وفك ترميز URL](https://acrafto.com/ar/url-encoder-decoder/) ([Markdown](https://acrafto.com/ar/url-encoder-decoder/index.md))
- हिन्दी (hi): [URL एन्कोडर और डिकोडर](https://acrafto.com/hi/url-encoder-decoder-online/) ([Markdown](https://acrafto.com/hi/url-encoder-decoder-online/index.md))
- Bahasa Indonesia (id): [URL encoder dan decoder](https://acrafto.com/id/url-encode-decode-online/) ([Markdown](https://acrafto.com/id/url-encode-decode-online/index.md))
- Tiếng Việt (vi): [Mã hóa và giải mã URL](https://acrafto.com/vi/url-encode-decode-truc-tuyen/) ([Markdown](https://acrafto.com/vi/url-encode-decode-truc-tuyen/index.md))
- ไทย (th): [URL Encode และ Decode](https://acrafto.com/th/url-encode-decode-online/) ([Markdown](https://acrafto.com/th/url-encode-decode-online/index.md))
- עברית (he): [מקודד ומפענח URL](https://acrafto.com/he/url-encoder-decoder/) ([Markdown](https://acrafto.com/he/url-encoder-decoder/index.md))
