URL Encoder & Decoder (Free, No Upload)
Percent-encode or decode any text instantly, in the right mode for the job — encodeURIComponent, encodeURI, form encoding or strict RFC 3986. Everything runs 100% in your browser.
Component mode: A single value going into a URL — a query value, a path segment, a slug.
25 characters · 31 UTF-8 bytes
71 characters · 71 UTF-8 bytes
Per-character breakdown
Every character of your input under Component mode: its code point, its UTF-8 bytes, what it becomes, and why. This is the fastest way to see the difference between the four modes — switch modes above and watch the table change.
| Char | Code point | UTF-8 bytes | Output | Why |
|---|---|---|---|---|
| C | U+0043 | 43 | C | Unreserved — never needs encoding. |
| + | U+002B | 2B | %2B | Reserved delimiter — encoded so it is treated as data, not structure. |
| + | U+002B | 2B | %2B | Reserved delimiter — encoded so it is treated as data, not structure. |
| ␣ | U+0020 | 20 | %20 | Space is not allowed in a URL — encoded as %20. |
| & | U+0026 | 26 | %26 | Reserved delimiter — encoded so it is treated as data, not structure. |
| ␣ | U+0020 | 20 | %20 | Space is not allowed in a URL — encoded as %20. |
| c | U+0063 | 63 | c | Unreserved — never needs encoding. |
| a | U+0061 | 61 | a | Unreserved — never needs encoding. |
| f | U+0066 | 66 | f | Unreserved — never needs encoding. |
| é | U+00E9 | C3 A9 | %C3%A9 | Non-ASCII — encoded as its 2 UTF-8 bytes. |
| ␣ | U+0020 | 20 | %20 | Space is not allowed in a URL — encoded as %20. |
| 😀 | U+1F600 | F0 9F 98 80 | %F0%9F%98%80 | Non-ASCII — encoded as its 4 UTF-8 bytes. |
| ␣ | U+0020 | 20 | %20 | Space is not allowed in a URL — encoded as %20. |
| — | U+2014 | E2 80 94 | %E2%80%94 | Non-ASCII — encoded as its 3 UTF-8 bytes. |
| ␣ | U+0020 | 20 | %20 | Space is not allowed in a URL — encoded as %20. |
| 1 | U+0031 | 31 | 1 | Unreserved — never needs encoding. |
| 0 | U+0030 | 30 | 0 | Unreserved — never needs encoding. |
| 0 | U+0030 | 30 | 0 | Unreserved — never needs encoding. |
| % | U+0025 | 25 | %25 | The % sign itself — must be escaped, or it would look like an escape. |
| ␣ | U+0020 | 20 | %20 | Space is not allowed in a URL — encoded as %20. |
| s | U+0073 | 73 | s | Unreserved — never needs encoding. |
| u | U+0075 | 75 | u | Unreserved — never needs encoding. |
| r | U+0072 | 72 | r | Unreserved — never needs encoding. |
| e | U+0065 | 65 | e | Unreserved — never needs encoding. |
| ? | U+003F | 3F | %3F | Reserved delimiter — encoded so it is treated as data, not structure. |
Do it in code
The same encoding in your language, for the current input and mode:
encodeURIComponent("C++ & café 😀 — 100% sure?")urllib.parse.quote("C++ & café 😀 — 100% sure?", safe="!~*'()")rawurlencode("C++ & café 😀 — 100% sure?") // closest equivalent — it also escapes ! ' ( ) *curl -G "https://example.com/search" --data-urlencode "q=C++ & café 😀 — 100% sure?" # note: --data-urlencode always uses form encoding (+ for spaces)
URL encoder & decoder, free and 100% in your browser
URL encoding replaces characters that are not allowed in a URL with a % sign plus two hex digits — the byte value of the character. becomes %20, & becomes %26, é becomes %C3%A9 (its two UTF-8 bytes), and 😀 becomes %F0%9F%98%80 (four bytes). The tool above does both directions live as you type, with four clearly labelled modes, a per-character breakdown that shows exactly why each byte was encoded, an integrated query-string parser, double-encoding detection, and honest, pinpointed errors when your input is malformed. Paste URLs with API keys or tokens without fear — nothing leaves your browser.
TL;DR
- Encode/decode live: type or paste and see the result instantly, with copy, swap, and sample inputs.
- Four modes, no confusion: Component (encodeURIComponent), Full URL (encodeURI), Form data (space → +), Strict RFC 3986 — each labelled with when to use it.
- See the why: a per-character table shows every code point, its UTF-8 bytes, its %XX output, and the reason it was encoded.
- Private: 100% client-side — unlike server-side tools, your tokens and URLs are never uploaded.
What is URL encoding? (the 60-second version)
URLs were designed for a tiny alphabet — the 66 RFC 3986 unreserved characters (A–Z, a–z, 0–9, -._~). Everything else must be percent-encoded: the character is converted to bytes (UTF-8 for non-ASCII), and each byte becomes %XX. Decoding reverses it. The tricky part is not the mechanism but the mode: a value going into a query needs & encoded (or it splits the query), a full URL must not have its slashes encoded (or it stops being a URL), and form data turns spaces into +. The four modes above exist because there is no single correct answer for a given string.
Which mode should I use?
| Mode | Use when | Leaves unescaped |
|---|---|---|
| Component | One value inserted into a URL — query value, path segment, slug (default) | A–Z a–z 0–9 - _ . ! ~ * ' ( ) |
| Full URL | A complete, already-structured URL | component set + ; / ? : @ & = + $ , # |
| Form | HTML form / query-string data — space becomes + | A–Z a–z 0–9 * - . _ |
| Strict RFC 3986 | Maximum safety — specs, signatures, OAuth flows | A–Z a–z 0–9 - . _ ~ |
This tool vs the classic URL encoders
| Property | This tool | meyerweb / urlencoder.org |
|---|---|---|
| Modes | Component, Full URL, Form and Strict RFC 3986 — each with a “use this when” line | meyerweb: encodeURIComponent only. urlencoder.org: no mode choice visible. |
| Private by default | 100% in your browser, zero network requests | urlencoder.org processes input on its servers by default (client-side is an opt-in “Live mode”) |
| Malformed input | Pinpointed: the category, the character position, and the offending substring — plus a labelled lenient repair | meyerweb silently does nothing; urldecoder.io turns the box red and clears the output |
| Double encoding | Detected with a depth indicator and one-click “decode one more level” | Not detected anywhere among the named tools — urldecoder.org just decodes 16 times with no explanation |
| Query parser & per-character table | Built in: editable params table, live URL rebuild, code-point/UTF-8 breakdown | Absent from every named incumbent |
The + pitfall: why plus means space in queries but not paths
This single character is the #1 source of URL encoding bugs. In a query string parsed as form data, + means space — so a literal plus must be sent as %2B, or C++ in a form query decodes as “C␣␣”. But in a path, + is a literal plus: /files/hello+world.txt is a file whose name contains plus signs. To make it worse, JavaScript's decodeURIComponent never converts + at all — you must replace it before decoding. The decode checkbox above does exactly that, in the correct order (a real %2B still survives as +), and the query parser has it on automatically because that is the only context where it applies.
What is double encoding? (%2520)
Double encoding is encoding an already-encoded string again. Since % itself encodes as %25, the sequence %20 becomes %2520. Decoding once gives %20 — still encoded, not a space. It happens when a framework auto-encodes a value you already encoded, or when redirects encode the same parameter on every hop. The detector above warns you whenever it sees %25 followed by two hex digits, shows the encoding depth, and offers one-click unwrapping — never an automatic fix, because sometimes double-encoded text is genuinely what you have to work with.
Common percent-encodings reference
| Character | Meaning / note | Encoded |
|---|---|---|
| Space | %20 | |
| ! | Exclamation mark | %21 |
| " | Double quote | %22 |
| # | Hash / fragment start | %23 |
| $ | Dollar | %24 |
| % | Percent (the escape sign itself) | %25 |
| & | Ampersand (separates parameters) | %26 |
| ' | Apostrophe | %27 |
| ( | Open parenthesis | %28 |
| ) | Close parenthesis | %29 |
| * | Asterisk | %2A |
| + | Plus (means space in form data) | %2B |
| , | Comma | %2C |
| / | Slash (path separator) | %2F |
| : | Colon | %3A |
| ; | Semicolon | %3B |
| < | Less than | %3C |
| = | Equals (key = value) | %3D |
| > | Greater than | %3E |
| ? | Question mark (starts the query) | %3F |
| @ | At sign | %40 |
| [ | Open bracket | %5B |
| \ | Backslash | %5C |
| ] | Close bracket | %5D |
| ^ | Caret | %5E |
| ` | Backtick | %60 |
| { | Open brace | %7B |
| | | Pipe | %7C |
| } | Close brace | %7D |
Careful with two of these: : is %3A — a popular encoder's reference table lists it as %3D, but that is the code for =. And é is two triplets, %C3%A9, because it is two UTF-8 bytes — every non-ASCII character encodes byte by byte, which is why the breakdown table above lists one row per character with all its bytes.
Is URL encoding the same as Base64?
No — this confusion sends a lot of people to the wrong tool. Base64 rewrites every byte into a 64-character alphabet (output ~33% larger, unreadable), and standard Base64 is not even URL-safe on its own. Percent-encoding only escapes what a URL cannot carry and leaves the rest — caf%C3%A9 still clearly reads café. Need Base64? Use our Base64 converter. Encoding tokens for headers? Try the JWT decoder instead.
Related tools
URL encoding is usually one step in a bigger job. Pretty-print the payload first with the JSON Formatter, encode it here, then spot the difference between two versions with the Text Diff Checker. For one-off opaque tokens, the Base64 converter is the right companion.
FAQs
What is URL encoding?+
URL encoding (percent-encoding) replaces characters a URL cannot safely carry with a % sign followed by two hex digits — the byte value of the character. A space becomes %20, an ampersand becomes %26, and the French é becomes %C3%A9 (its two UTF-8 bytes). It exists because URLs were designed for a tiny ASCII alphabet: anything outside it — spaces, accents, emoji, symbols with structural meaning — must be encoded so every server on the internet reads the URL the same way.
What does %20 mean in a URL?+
%20 is a space. The % starts a percent-encoded byte, and 20 (hex) is 32 in decimal — the ASCII code for a space. So "hello world" becomes "hello%20world". You will see the same pattern for other characters: %26 is &, %3F is ?, and %C3%A9 is é.
Why does a space become + instead of %20?+
That is form encoding — application/x-www-form-urlencoded, the format browsers use when an HTML form is submitted with GET. In that format, and only that format, a space is written as +. It is correct in query strings handled as form data, but wrong in paths: /files/hello+world.txt is a file literally named with plus signs. This tool has a dedicated Form mode that produces +, and a "decode + as space" toggle for reading form-encoded data.
What is the difference between encodeURI and encodeURIComponent?+
encodeURIComponent is for a single value going into a URL: it encodes everything except A–Z, a–z, 0–9 and - _ . ! ~ * ' ( ). encodeURI is for a whole, already well-formed URL: it additionally leaves ; / ? : @ & = + $ , # untouched so the URL's structure survives. The classic bug is calling encodeURI on a value that contains & — as MDN itself demonstrates, encodeURI("https://example.com/?choice=Ben & Jerry's") keeps the &, so the query parses as two parameters. Rule of thumb: whole URL → encodeURI; each value you insert → encodeURIComponent.
What characters must be URL encoded?+
Always encode: spaces, %, " < > \ ^ ` { | }, control characters, and every non-ASCII character (encoded as its UTF-8 bytes). In query values, also encode &, = and + because form/query conventions give them structural meaning — a literal + in a form query decodes as a space. The strict RFC 3986 set also encodes ! ' ( ) *, which JavaScript's built-ins leave as-is.
How do I encode a URL in JavaScript or Python?+
In JavaScript: encodeURIComponent(str) for a value, encodeURI(str) for a whole URL. For strict RFC 3986 add .replace(/[!"'()*]/g, c => "%" + c.charCodeAt(0).toString(16).toUpperCase()). In Python: urllib.parse.quote(text, safe="") is close to strict RFC 3986; quote_plus(text) produces form encoding (+ for spaces); quote(text, safe="!~*'()") approximates encodeURIComponent. In PHP: urlencode() = form encoding, rawurlencode() ≈ strict. The tool above has a "Do it in code" panel that generates these snippets for your exact input.
Is URL encoding the same as Base64?+
No. Base64 recodes every byte into a 64-character alphabet, making output ~33% larger and unreadable, and standard Base64 itself needs URL escaping. Percent-encoding only escapes the characters a URL cannot carry and leaves everything else readable — "caf%C3%A9" still clearly says café. They solve different problems; if you need Base64, use our Base64 converter.
Why does my decoded text show + instead of spaces?+
Because no built-in JavaScript decoder converts + to a space — not decodeURIComponent, not decodeURI, not even the deprecated unescape. The correct form decoding is to replace + with a space first, then percent-decode: decodeURIComponent(s.replace(/\+/g, " ")). The order matters: a genuine %2B must survive as +. This tool has a "Decode + as space" checkbox that does the replacement correctly; it defaults on in the query parser and off elsewhere.
When should I use + instead of %20 for spaces?+
Use + only in form-encoded query data — the format HTML forms submit and most servers expect in ?key=value pairs. Use %20 everywhere else: paths, fragments, slugs, and any value handled as a single opaque string. Many servers read both, which is why the confusion survives — but in a path, + is a literal plus, so %20 is the safe universal choice.
Is what I paste sent to a server?+
No. Encoding and decoding happen entirely in your browser using built-in JavaScript APIs — you can verify this in the Network tab, or disconnect from the internet and the tool still works. This matters because URLs routinely carry tokens, API keys and session IDs: popular tools like urlencoder.org process your input on their servers by default. Nothing you paste here ever leaves your device.
More free tools
Want guides and tips? Visit the ToolsOfWeb blog or go back to the homepage.
