URL Encode / Decode

Percent-encode or decode URLs and URL components instantly. Pick Component (a query value or path piece) or Full URI (a whole URL). Runs entirely in your browser. Last reviewed 2026-06-19.

How URL (percent) encoding works

A URL may only contain a limited set of characters. Anything outside that set — spaces, most punctuation, and non-ASCII text — is replaced by % followed by the character's UTF-8 byte values in hexadecimal. A space becomes %20, an ampersand %26, and é becomes %C3%A9.

Component vs. full URI

This is the distinction most tools blur. Component mode (encodeURIComponent) encodes the reserved structural characters too (: / ? # [ ] @ & = +), so it is correct for a single query-string value or path segment. Full-URI mode (encodeURI) leaves those structural characters intact and only fixes spaces and illegal characters, so it is for encoding a whole URL at once. Using the wrong one is a common source of broken links.

Reserved vs. unreserved characters

Per RFC 3986, the unreserved characters A–Z a–z 0–9 - _ . ~ are never encoded. Reserved characters have a structural meaning in a URL and are encoded only when they appear as data rather than as delimiters.

The complete RFC 3986 character sets

The modern rulebook for URLs is RFC 3986, published in January 2005. It obsoletes the older RFC 2396 (and RFC 1808 and RFC 2732) and updates the original URL specification RFC 1738. RFC 3986 divides the ASCII characters a URI may use into three groups, and getting them right is the whole game.

GroupCharactersRole
UnreservedA–Z a–z 0–9 - _ . ~Always safe; never need encoding and should not be encoded unnecessarily.
Reserved — gen-delims: / ? # [ ] @Major structural separators between scheme, authority, path, query and fragment.
Reserved — sub-delims! $ & ' ( ) * + , ; =Sub-component delimiters, for example the dividers between query parameters.

Reserved characters carry meaning as delimiters. A URI that differs from another only in the percent-encoding of an unreserved character is considered equivalent, so encoding A as %41 is legal but pointless and well-behaved software normalizes it back. Reserved characters, by contrast, must be percent-encoded whenever they appear as literal data rather than as a separator: an ampersand inside a search term has to become %26 so it is not mistaken for the divider between two query parameters.

How a character becomes a percent-encoded octet

Percent-encoding works on bytes, not on characters directly. RFC 3986 defines the triplet grammar pct-encoded = "%" HEXDIG HEXDIG: a literal percent sign followed by two hexadecimal digits that spell out one 8-bit octet. The space character (US-ASCII value 32, binary 00100000, hex 20) therefore encodes to %20.

For anything beyond plain ASCII the rule is unambiguous in modern URLs: encode the text as UTF-8 first, then percent-encode each resulting byte that is not in the unreserved set. Because most non-ASCII characters occupy two, three or four UTF-8 bytes, they expand into several triplets. The accented é becomes %C3%A9; the Japanese katakana letter a (ア) becomes %E3%82%A2; a four-byte character such as an emoji expands to four triplets. The JavaScript built-ins this tool uses already follow UTF-8, which is why round-tripping accents, CJK text and emoji works correctly.

encodeURI, encodeURIComponent and the deprecated escape

JavaScript ships three encoders, and confusing them is a classic bug. The table below lists exactly which characters each one leaves un-encoded — everything else becomes a percent-triplet.

FunctionLeaves unencodedUse it for
encodeURIComponentA–Z a–z 0–9 - _ . ! ~ * ' ( )A single value: one query parameter, one path segment or a form field.
encodeURIThe above plus ; / ? : @ & = + $ , #A whole, already-structured URL where the separators must survive.
escape (deprecated)A–Z a–z 0–9 @ * _ + - . /Nothing — avoid it entirely.

The eleven punctuation marks - _ . ! ~ * ' ( ) that even encodeURIComponent leaves alone are the RFC 3986 unreserved marks together with a few legacy characters. Everything structural — : / ? # [ ] @ and the crucial &, = and + — is encoded, which is exactly why encodeURIComponent is the right choice for an individual value. The legacy escape function is deprecated and non-standard: it does not use UTF-8 (it emits %XX for code points below 256 and a non-standard %uXXXX form above that), so a character like ć wrongly becomes %u0107 instead of its UTF-8 bytes. Never use it for URLs.

The space problem: %20 versus +

One byte causes more confusion than any other: the space. In a generic URI per RFC 3986 a space is %20. But HTML forms submitted as application/x-www-form-urlencoded follow a different, older convention — defined today in the WHATWG URL Standard — where a space becomes a literal plus sign +, and a literal plus is therefore encoded as %2B to keep the two apart. The browser's URLSearchParams API uses this form encoding, so it serializes a space as +, whereas encodeURIComponent produces %20.

Both are valid in the query string of a real URL, and a correct decoder treats + as a space only in form-encoded data — never in a path. Decoding + to a space inside a path segment is a common bug that corrupts file names and slugs. If you paste form data here and want plus signs treated as spaces, replace them before decoding; for ordinary URLs, leave them as they are.

Encoding depends on the part of the URL

A URL is not one flat string; it is a sequence of components — scheme, userinfo, host, port, path, query and fragment — and each has its own set of legal characters. The practical consequences:

  • Path segments may contain sub-delims and : @, but a literal / inside a single segment must be written %2F, or it is read as a new segment boundary.
  • Query strings treat & and = as separators, so any value containing them must be percent-encoded; ? and /, however, are allowed unescaped inside a query.
  • Fragments (after #) are never sent to the server — the browser handles them — but still follow percent-encoding for non-ASCII content.
  • Userinfo (the rarely-used user:password@ before the host) must encode @ and : when they appear as data rather than as the separators.

This is why a single "encode the whole thing" pass is wrong: encode each component with encodeURIComponent first, then join them with the literal structural characters you actually intend.

International domains and IRIs: Punycode, not percent-encoding

Percent-encoding handles non-ASCII text in the path, query and fragment, but it cannot be used in the host name — DNS accepts only a restricted ASCII alphabet. Internationalized domain names are instead converted with Punycode (RFC 3492) under the IDNA standard. Each non-ASCII label is transformed and given the ASCII-compatible prefix xn--: münchen.de becomes xn--mnchen-3ya.de, and the label bücher becomes xn--bcher-kva. Browsers display the friendly Unicode form but send the xn-- form on the wire.

The broader concept is the IRI (Internationalized Resource Identifier, RFC 3987), which permits Unicode throughout. An IRI is mapped to a plain URI by normalizing the text (Unicode NFC), UTF-8-encoding the non-ASCII characters in the path and query, and percent-encoding those bytes — while the host is converted with Punycode. So https://en.wiktionary.org/wiki/Ῥόδος becomes https://en.wiktionary.org/wiki/%E1%BF%AC%CF%8C%CE%B4%CE%BF%CF%82. In short: the host uses Punycode, everything else uses percent-encoding.

Double-encoding: the bug that adds a layer too many

Double-encoding happens when already-encoded text is encoded again. The percent sign is itself a reserved character, so encoding %20 a second time yields %2520 — because the leading % becomes %25. The reverse mistake, decoding once when two layers exist, leaves stray %xx sequences in the output. Symptoms include URLs that show %2520 in the address bar, or file names that arrive with a literal %20 baked into them.

The fix is to be deliberate about how many times a value is encoded as it passes through layers — your code, an HTTP library, a proxy, a framework's router — and to decode exactly that many times. Encode once, at the moment you build the URL; never run a value through an encoder twice "to be safe." To check a suspicious value, decode it here repeatedly: if a second decode changes the result, it was double-encoded.

Security: where naive encoding and decoding go wrong

URL encoding is a frequent ingredient in web vulnerabilities, almost always because a decoded value is trusted without re-validation.

  • Open redirects. A ?next= or ?return_to= parameter that is decoded and used as a redirect target lets an attacker send users to a hostile site. Validate the decoded destination against an allow-list of hosts — never redirect to an arbitrary decoded URL.
  • Cross-site scripting (XSS). Decoding turns %3Cscript%3E back into a live tag. If that decoded text is written into a page without HTML-escaping it can execute. Percent-decoding and HTML-escaping are different jobs: do the second before the value reaches the DOM.
  • Filter and WAF bypass. Attackers encode and double-encode payloads — ..%2F for ../, or %2527 for a quote — to slip past a filter that only inspects the raw form. Normalize input to a single canonical decoded form before applying security checks, not after.
  • Log and header injection. A decoded newline (%0A) or carriage return (%0D) injected into a value that ends up in a log line or HTTP header can forge entries or split a response. Strip control characters after decoding.

The throughline: percent-encoding is a transport convenience, not a security boundary. Always validate and contextually escape the decoded value for wherever it is finally used.

Beyond web links: other places percent-encoding appears

Percent-encoding is not limited to the https:// addresses in your browser bar; the same RFC 3986 rules govern many other identifiers, and the per-context discipline above applies to each.

  • mailto: links. A pre-filled email link such as mailto:hi@example.com?subject=Hello%20there&body=Line%20one uses percent-encoding for spaces and punctuation in the subject and body, and an ampersand to separate the fields — so any literal ampersand in the body text must itself be %26.
  • data: URIs. Inline resources like data:text/plain,Hello%20World percent-encode their payload (or carry it as Base64 instead), which is why this tool pairs naturally with a Base64 encoder.
  • OAuth and redirect parameters. An OAuth redirect_uri is a whole URL nested inside another URL's query string, so it must be encoded as a single component with encodeURIComponent — a textbook case where forgetting to encode (or double-encoding) silently breaks the login flow.
  • HTTP authentication and APIs. Credentials placed in the userinfo component, signed-request signatures and many REST path parameters all rely on consistent, single-pass percent-encoding so that the value the server reconstructs matches the value you sent.

In each of these settings the failure mode is identical to a broken web link: a reserved character that was meant as data slips through as a delimiter, or an encoded value is decoded one time too few or too many. Encode each value once, for the exact slot it occupies, and the identifier round-trips cleanly everywhere.

Frequently asked questions

What is URL encoding?
URL (percent) encoding replaces characters that are unsafe or reserved in a URL with a "%" followed by their hexadecimal byte value — for example a space becomes %20 and an ampersand becomes %26. It lets arbitrary text travel safely inside a URL.
Component mode vs full-URI mode — which do I use?
Use "Component" (encodeURIComponent) when encoding a single piece that goes inside a URL — a query-string value, a path segment or a form field — because it also encodes :/?#[]@&=+ etc. Use "Full URI" (encodeURI) when you have a whole URL and only want to fix spaces and illegal characters while leaving the structural characters intact.
Does it handle Unicode and emoji?
Yes. Encoding is done over UTF-8, so accented letters, non-Latin scripts and emoji percent-encode and decode back correctly.
Is anything sent to a server?
No. Encoding and decoding run entirely in your browser, so your data stays on your device. The tool also works offline once loaded.

Related tools

See all developer & data conversions →

Jelajahi alat lainnya

Lihat semua 70 alat →

Sematkan alat ini di situs Anda — gratis

Semua alat yang bisa disematkan →

Tambahkan URL Encode / Decode ke halaman, postingan, atau template apa pun. Gratis selamanya — tanpa pendaftaran, tanpa iklan di dalam widget. Satu-satunya syarat: pertahankan tautan atribusi kecil yang terlihat.

Pratinjau widget