Percent-encode and decode URLs instantly. Compare encodeURIComponent, encodeURI and form encoding, parse query strings, and catch double-encoding bugs.
Paste a URL or a fragment of text and this tool percent-encodes or decodes it as you type. It handles the three encodings that actually matter in practice — encodeURIComponent, encodeURI, and application/x-www-form-urlencoded form encoding — and it warns you when it detects double-encoding, which is the single most common cause of mysterious broken links. It also parses a URL into its component parts and breaks a query string into readable key/value pairs. Everything runs in your browser; nothing is uploaded.
Percent encoding (often called URL encoding) is the mechanism defined in RFC 3986 for representing arbitrary bytes inside a URL. Each byte that cannot appear literally is written as a percent sign followed by two hexadecimal digits: a space becomes %20, an ampersand becomes %26, and a non-ASCII character becomes the percent-encoded form of its UTF-8 bytes, so é becomes %C3%A9.
RFC 3986 splits the character space into three groups, and knowing which is which explains almost every encoding decision.
Unreserved characters never need encoding and should never be encoded: the letters A–Z and a–z, the digits 0–9, and the four marks - . _ ~. Encoding these is harmless in the sense that decoders accept it, but it makes URLs longer and breaks byte-for-byte comparison, so tools that normalise URLs will decode them back.
Reserved characters carry structural meaning: : / ? # [ ] @ are the generic delimiters, and ! $ & ' ( ) * + , ; = are sub-delimiters. These must be encoded when they appear as data and left alone when they act as syntax. That distinction is the entire game. A / separating path segments stays literal; a / inside a filename that happens to be a query value must become %2F.
Everything else — spaces, control characters, and all non-ASCII text — must always be percent-encoded.
This is the choice that causes the most bugs, and the rule is simpler than it looks: encode the whole URL with encodeURI, encode a piece that goes inside a URL with encodeURIComponent.
encodeURIComponent encodes everything except A–Z a–z 0–9 - _ . ! ~ * ' ( ). Because it encodes the reserved delimiters too, it is safe for a value that must not be allowed to alter the URL’s structure — a query parameter value, a single path segment, a fragment identifier.
encodeURI deliberately leaves the reserved structural characters alone: : / ? # [ ] @ ! $ & ' ( ) * + , ; = all survive. It exists to clean up an already-assembled URL that contains spaces or accented characters, without destroying the URL itself.
The tool’s comparison table makes the difference concrete:
| Character | encodeURIComponent | encodeURI | Form data |
|---|---|---|---|
| space | %20 | %20 | + |
| / | %2F | / | %2F |
| ? | %3F | ? | %3F |
| # | %23 | # | %23 |
| & | %26 | & | %26 |
| = | %3D | = | %3D |
| : | %3A | : | %3A |
| @ | %40 | @ | %40 |
| + | %2B | + | %2B |
The classic failure: you build a redirect link as ?next= plus a full URL and reach for encodeURI. The & and = inside the nested URL stay literal, the server splits the query string on them, and your redirect target arrives truncated. The nested URL is a value, so it needs encodeURIComponent.
The correct encoding depends on where in the URL the text lands.
Query parameter values should be encoded with encodeURIComponent. The delimiters &, =, and # must not survive literally, or the parameter boundary moves.
Path segments also need encodeURIComponent, and the critical character is /. If a segment can contain a slash — a file path used as an identifier, for instance — leaving it literal silently adds a path segment and routes the request somewhere else entirely.
Form data is the historical oddity. The application/x-www-form-urlencoded serialisation, inherited from HTML forms, encodes a space as + rather than %20 and therefore has to encode a literal plus sign as %2B. Both conventions are alive today, which is why a search box query containing “C++” so often comes back as “C ”: something decoded + as a space in a context that used %20 semantics. This tool’s Form Data mode reproduces the form encoding exactly so you can reproduce and diagnose that class of bug.
One more asymmetry worth remembering: %20 is valid everywhere in a URL, but + only means “space” inside a query string. In a path segment, + is a literal plus. When in doubt, use %20.
Double encoding happens when already-encoded text is encoded a second time. The percent sign is itself a reserved character, so % becomes %25, and a space that was %20 becomes %2520. Decode once and you get %20 back — a literal string, not a space. The link looks almost right and behaves wrong.
The telltale signatures are %2520 (double-encoded space), %253A and %252F (double-encoded : and /, so a nested https%3A%2F%2F becomes https%253A%252F%252F), and %2526. This tool detects those patterns automatically and shows a warning with the offending sequence, in both encode and decode mode. In decode mode the fix is simply to decode again; in encode mode the warning means your input was already encoded and you should decode it first.
Double encoding usually comes from a value passing through two layers that each “helpfully” encode — an HTTP client library plus your own call to encodeURIComponent, or a proxy that re-encodes what it forwards. Encode exactly once, at the boundary where the string is inserted into the URL.
encodeURIComponent) for parameter values and path segments, Full URL (encodeURI) for a complete URL, Form Data for x-www-form-urlencoded payloads.Percent encoding is one of several encodings you will meet in the same debugging session. Use the Base64 encoder and decoder when a value is Base64 rather than percent-encoded — Base64url in particular replaces + and / with - and _ specifically to avoid URL encoding issues. Use the JWT decoder for bearer tokens, whose segments are Base64url. If the value you are untangling turns out to be JSON, the JSON formatter will make it readable, and the regex tester helps when you need to match encoded sequences in bulk.
URL encoding, or percent encoding, replaces characters that cannot appear literally in a URL with a % followed by two hex digits representing the character’s bytes in UTF-8. It is defined in RFC 3986.
%20 is a space character. 0x20 is the ASCII code for space. In query strings you may also see + used for a space, which comes from HTML form encoding rather than from RFC 3986.
Use encodeURIComponent for any single piece being inserted into a URL — a query value, a path segment, a fragment. Use encodeURI only when you already have a complete, correctly structured URL and just need to clean up spaces or non-ASCII characters in it.
It has been encoded twice. A space became %20, then the % was encoded again as %25, producing %2520. Decode it twice to recover the original, then fix the code path so it encodes only once.
Because application/x-www-form-urlencoded defines + as a space. If your value contains a literal plus, encode it as %2B. This is why version strings and expressions like “C++” get mangled by search forms.
Yes. Non-ASCII characters are encoded as their UTF-8 bytes, so each character becomes two to four percent-escapes. Browsers often display the decoded form in the address bar even though the encoded form is what is sent over the wire.
No. Percent encoding is a transport format, not a protection mechanism — anyone can decode it instantly. It does not hide data and it is not a substitute for validating and escaping input on the server. Encoding correctly does, however, prevent a class of injection bugs caused by attacker-supplied delimiters escaping their intended field.
No. All encoding, decoding, parsing, and analysis happens locally in your browser. Nothing is transmitted or stored.
URL encoding (also called percent-encoding) converts characters into a format that can be safely transmitted in a URL. URLs can only contain a limited set of ASCII characters: letters, digits, and a few special characters like hyphens and underscores. Any other character—spaces, non-ASCII letters, special symbols—must be encoded as a percent sign followed by two hexadecimal digits representing the character's byte value.
This encoding scheme is defined in RFC 3986 and is fundamental to how the web works. Every time you search for something with spaces, submit a form, or share a URL containing special characters, URL encoding is happening behind the scenes. Understanding it is essential for web developers, API designers, security professionals, and anyone working with HTTP requests.
URL encoding replaces unsafe characters with a percent sign (%) followed by their hexadecimal ASCII value. Multi-byte characters (like Unicode) are first encoded in UTF-8, then each byte is percent-encoded individually.
| Character | Encoded | Reason |
|---|---|---|
| Space | %20 or + | Delimiter in URLs |
| & | %26 | Query parameter separator |
| = | %3D | Key-value pair separator |
| ? | %3F | Query string start marker |
| # | %23 | Fragment identifier |
| / | %2F | Path separator |
| @ | %40 | Userinfo separator |
| + | %2B | Interpreted as space in forms |
| % | %25 | Encoding escape character itself |
Reserved characters have special meaning in URLs (/, ?, &, =, #, @). They must be encoded when used as data rather than as delimiters. Unreserved characters (A-Z, a-z, 0-9, -, _, ., ~) never need encoding.
For example, searching for "C++ programming" in a query string becomes: q=C%2B%2B+programming or q=C%2B%2B%20programming.
encodeURIComponent(), Python's urllib.parse.quote(), and similar built-in functions handle encoding correctlyURL encoding (percent-encoding) converts special characters to safe format for URLs using %XX notation where XX is hexadecimal ASCII code. Example: space becomes %20, @ becomes %40. Necessary because: URLs only support ASCII characters, special characters have meaning in URLs (? starts query, & separates parameters, # is fragment), spaces not allowed, non-ASCII characters (中文, émoji) need encoding. Without encoding: "https://site.com?search=hello world" breaks (space invalid). Encoded: "?search=hello%20world". Used in: query parameters, path segments, form data. Not needed in: domain names (use punycode), within HTML (different escaping). This tool encodes/decodes instantly.
encodeURI encodes full URL, preserving URL structure characters (:, /, ?, &, #). Example: encodeURI("http://example.com/path?q=hello world") = "http://example.com/path?q=hello%20world". encodeURIComponent encodes URI parts, encodes ALL special characters including URL structure. Example: encodeURIComponent("hello world&foo=bar") = "hello%20world%26foo%3Dbar". Use encodeURI for: complete URLs before sending. Use encodeURIComponent for: query parameter values, form inputs, API parameters. Common mistake: using encodeURI on query values - breaks &, =. Best practice: encodeURIComponent for all user input in URLs. This tool supports both modes with visual difference comparison.
Reserved characters (special meaning): : / ? # [ ] @ ! $ & ( ) * + , ; = - must encode in data, not structure. Unsafe characters: space " < > % { } | \ ^ ~ [ ] ` - always encode. Non-ASCII: 中文, émojis, accents (é, ñ) - encode. Unreserved (safe, no encoding needed): A-Z a-z 0-9 - _ . ~. Example: "hello world!" → "hello%20world%21". Common encodings: space = %20 or +, @ = %40, # = %23, & = %26, = = %3D. Double encoding: avoid encoding twice (%20 → %2520). Decode before re-encoding. This tool highlights which characters require encoding and provides character encoding reference.
Query strings start with ? and use & to separate parameters. Format: ?key1=value1&key2=value2. Encode each value separately: ?search=encodeURIComponent(userInput). Example: search="coffee & tea" → ?search=coffee%20%26%20tea. Array parameters: ?tags[]=a&tags[]=b or ?tags=a,b (depends on server). Spaces: %20 or + (both valid in query strings). Equals in value: encode = as %3D. Ampersand in value: must encode & as %26 (otherwise starts new parameter). Build query: use URLSearchParams (JavaScript) or http.build_query (PHP). Never concatenate manually: "?search=" + input (unsafe!). This tool safely encodes query parameters with proper & and = handling.
Different contexts call for different encoding. URL encoding (for URLs and URIs) uses %XX hexadecimal: a space becomes %20 and < becomes %3C. HTML encoding (for HTML content) uses &name; entities: a space becomes or a plain space, and < becomes <. Example: the string a<b&c>d becomes a%3Cb%26c%3Ed with URL encoding and a<b&c>d with HTML encoding. Context matters: a URL parameter that carries HTML content needs both layers. encodeURIComponent(x) gives a value like a%3Cb%3E, which then sits inside HTML markup such as <a href="?q=a%3Cb%3E">. Do not mix them: a %20 placed in HTML text shows up literally, and a < placed in a URL breaks it. This tool focuses on URL encoding - use an HTML encoder for HTML entities.
URL paths (between slashes): encode most special characters but / separates path segments. Example: /api/users/john%20doe (space encoded, / not). Some servers allow: - _ . ~ in paths unencoded. Query strings (after ?): encode = & ? # since they have special meaning. Example: ?name=john%26jane (& must be encoded). Fragment (after #): similar to query encoding. Best practices: always encode user input regardless of position, encodeURIComponent for both paths and queries is safe, server frameworks handle decoding automatically. Double slashes: avoid // in paths (may normalize to /). This tool helps identify correct encoding per URL component.
Double encoding: encoding already-encoded URL. "hello%20world" → "hello%2520world" (wrong). Check before encoding. Not encoding user input: leaving special characters unencoded creates XSS vulnerabilities. Always encode untrusted input. Using encodeURI on parameters: preserves &, = (breaks query string). Use encodeURIComponent for parameter values. Encoding too much: encoding entire URL with structure makes http become http%3A%2F%2F. Encode parts separately. Forgetting to decode: displaying "hello%20world" to user (shows %20). Decode for display. Plus sign ambiguity: + can mean space in query strings but not in paths. Use %20 for clarity. Wrong encoding in POST body: use application/x-www-form-urlencoded header. This tool prevents double-encoding and validates output.
Non-ASCII characters (中文, émoji, é) convert to UTF-8 bytes then percent-encode each byte. Example: "café" → c (63) a (61) f (66) é (C3 A9 in UTF-8) → "caf%C3%A9". Emoji "😀" → %F0%9F%98%80 (4 bytes). Modern browsers handle automatically, but APIs may need explicit encoding. Punycode for domains: "münchen.de" → "xn--mnchen-3ya.de" (different encoding). IDN (Internationalized Domain Names) handled separately from path/query encoding. Best practice: use UTF-8 everywhere, let libraries handle encoding (encodeURIComponent uses UTF-8), test with actual international characters. This tool correctly handles UTF-8 multibyte characters and shows byte-level encoding.