URL Encode / Decode — Free Online Tool
Percent-encode and decode URLs online in 30+ character sets. Component mode mirrors encodeURIComponent, full-URI mode keeps reserved characters intact.
Use this free online URL Encode / Decode directly in your browser. No signup required, no data leaves your device. Part of Utilier — a collection of 133+ developer utilities.
What is URL Encoder / Decoder (Percent-Encoding)?
URL encoding — called percent-encoding in RFC 3986 — replaces characters that a URL cannot carry literally with a % followed by the two hex digits of each byte. A space becomes %20, an @ becomes %40, and any non-ASCII character becomes one escape per byte of its encoded form. This tool runs that transformation in both directions, entirely in your browser.
Percent-encoding works on UTF-8 bytes, not on visual characters. It is used for URL components such as query parameter values and path segments, where spaces, ampersands, slashes, and non-ASCII text could otherwise change how a browser or server parses the URL. Encoding a whole URL blindly can corrupt its separators, so encode the relevant component instead.
- Two encoding modes: Component mode escapes everything except A–Z a–z 0–9 and - _ . ! ~ * ' ( ), matching JavaScript's encodeURIComponent — correct for a single query value or path segment. Turning it off mirrors encodeURI, leaving the reserved set : / ? # [ ] @ ! $ & ' ( ) * + , ; = intact so a whole URL stays a URL.
- Character-set aware: encodeURIComponent always emits UTF-8. This tool encodes through the charset you choose — 30 labels covering UTF-8, UTF-16LE/BE, US-ASCII, the ISO-8859-1…16 family, Windows-1250…1258, and KOI8-R/U — which is what legacy endpoints and older CMS query strings actually expect.
- Byte-run decoding: On decode, consecutive %XX escapes are collected into one byte run and decoded together, so multi-byte UTF-8 sequences such as %E4%B8%96 round-trip to 世 instead of three replacement characters.
- Honest failures: If a character cannot be represented in the target charset, the tool names the character and its code point (for example "世" (U+4E16) can't be represented in iso-8859-1) rather than silently substituting a ? or a mojibake byte.
Why use url codec?
A URL has a grammar, and unescaped user data breaks it. Percent-encoding is what keeps a value a value instead of letting it become a delimiter, and it is the difference between a working link and a truncated, mis-parsed, or exploitable one.
- Stops silent data loss: An unencoded & or = ends a parameter early: ?note=Tom & Jerry arrives as note=Tom, and " Jerry" is discarded or parsed as a second parameter. An unencoded # discards everything after it before the request is even sent, because the fragment never leaves the browser.
- Removes a class of injection bug: Reflecting raw input into a URL is how parameter injection, open redirects, and response-splitting attempts start. Escaping the reserved set means attacker-supplied text cannot introduce new delimiters.
- Handles legacy charsets that built-ins cannot: If an endpoint reads query strings as Windows-1251 or Shift-style single-byte tables, UTF-8 escapes decode to garbage on its side. Selecting the charset here produces the byte sequence that endpoint expects.
- Debug what you actually received: Paste a percent-encoded string from a log line, an OAuth signature, or a Referer header and read it back as text — including double-encoded values, which show up as literal %2520 and decode in two passes.
When to use url codec
Reach for it whenever text crosses into a URL, or when a URL you were handed does not behave the way you expect.
- Building query strings by hand: search terms, filter values, emails, file names, or anything containing spaces, +, &, =, #, %, or non-Latin script.
- Interpolating a value into a path segment, where an unescaped / would create a new segment and change the route.
- Signing requests: OAuth 1.0a and AWS SigV4 both require RFC 3986 percent-encoding of every parameter before the signature base string is assembled, and both fail with a generic signature error if the encoding differs by a single character.
- Reading logs, analytics reports, or Referer/UTM values back into plain text to see what a user actually submitted.
- Diagnosing mojibake: decoding the same string as UTF-8 and then as Windows-1252 or ISO-8859-1 usually identifies which side has the wrong assumption.
- Migrating content between systems whose URLs were generated in a legacy charset, where the old escapes must be decoded in that charset and re-encoded as UTF-8.
How to use url codec
Both directions use the same two settings, so decide what part of the URL you are handling before you press a button.
- Paste the text or URL: Put the raw value in the input box — a single parameter value, a path segment, or a complete URL.
- Choose component or full-URI mode: Leave "Component mode" checked for one value (it escapes / ? & = # too). Uncheck it when the input is an entire URL you want to keep usable, so the structural characters survive.
- Pick the character set: Keep UTF-8 unless the other system documents something else; switch to ISO-8859-1, a Windows-125x code page, or KOI8-R/U when you are targeting or reading legacy output.
- Press Encode or Decode: Encode produces the escaped form; Decode groups %XX runs and turns them back into text using the selected charset.
- Verify by round-tripping: Use the swap control to feed the result back as input and run the opposite operation. Getting your original string back confirms both the mode and the charset were right.
Key features
- encodeURIComponent and encodeURI parity: One checkbox switches between the two safe sets JavaScript exposes, so output matches what your code will produce at runtime.
- 30 character sets: UTF-8, UTF-16LE, UTF-16BE, US-ASCII, ISO-8859-1 through ISO-8859-16, Windows-1250 to Windows-1258, KOI8-R and KOI8-U, grouped in the picker.
- Multi-byte safe both ways: Encoding emits one escape per byte; decoding reassembles byte runs before converting, which is what makes emoji and CJK text survive the trip.
- Uppercase hex output: Escapes are emitted as %2F rather than %2f — the form RFC 3986 prefers, and what signature algorithms that compare strings byte-for-byte expect.
- Swap and re-run: Move the output back into the input in one click to decode what you just encoded, or to peel a second layer off a double-encoded value.
- Local and private: Everything happens in the page via TextEncoder/TextDecoder. Tokens, signed URLs, and customer data in query strings never leave the browser.
Common use cases
- API integration: Encode path and query values before assembling a request, and decode error payloads that echo the offending URL back at you.
- OAuth and request signing: Produce the strict RFC 3986 escaping that signature base strings require, including %20 for spaces and escaped ( ) when a provider demands it.
- Analytics and campaign links: Encode UTM values that contain spaces or ampersands so the whole campaign name survives instead of being cut at the first special character.
- Log and incident analysis: Turn escaped request lines from access logs back into readable text while investigating a bug or an abuse report.
- Legacy migration: Decode URLs generated by an old Windows-125x application and re-encode them as UTF-8 for a new stack, keeping redirects intact.
- Learning and review: Show exactly which characters change under each mode — useful in code review when arguing for encodeURIComponent over string concatenation.
Examples
Component mode, UTF-8 unless noted. Click the copy icon to copy any value.
Spaces and reserved characters in a query value
Tom & Jerry: season 1/2Tom%20%26%20Jerry%3A%20season%201%2F2The & : and / are all escaped, so the value cannot end the parameter or add a path segment.
Email address as a parameter
user+filter@example.comuser%2Bfilter%40example.comEscaping the + matters: many form parsers would otherwise read it as a space and break the address.
Full URL, component mode off
https://example.com/search?q=hello world&page=2https://example.com/search?q=hello%20world&page=2Full-URI mode keeps :// ? & and = literal so the URL still works, and only fixes the space.
Non-ASCII text in UTF-8
Hello 世界 🌍Hello%20%E4%B8%96%E7%95%8C%20%F0%9F%8C%8DThree bytes per CJK character, four for the emoji — one escape per byte, which is why the output looks long.
Same text in a legacy charset
GrüßeGr%FC%DFeEncoded as ISO-8859-1: one byte per character. In UTF-8 the same string is Gr%C3%BC%C3%9Fe — decoding with the wrong charset is what produces Grüße.
Double-encoded value
hello%2520worldhello%20worldOne decode pass reveals a still-encoded string; decode again to reach "hello world". A literal %25 in the input is the signature of double encoding.
Technical reference
The rules this tool follows:
- Specification
- RFC 3986 §2 (percent-encoding, reserved and unreserved sets); WHATWG URL Standard for the encoding labels
- Unreserved characters
- A–Z a–z 0–9 - . _ ~ — never require escaping, and decoding them changes nothing about how a URL is interpreted
- Component safe set
- A–Z a–z 0–9 - _ . ! ~ * ' ( ) — identical to encodeURIComponent
- Full-URI safe set
- The component set plus ; , / ? : @ & = + $ # — identical to encodeURI
- Escape format
- %HH per byte, uppercase hex digits
- Space
- %20 in URLs; + only inside application/x-www-form-urlencoded form data
- Default charset
- UTF-8, matching every modern browser and server default
Common mistakes to avoid
Encoding the whole URL with encodeURIComponent (or component mode left on)
Why it happens: Component mode escapes the characters that give a URL its structure. https://example.com/a?b=c becomes https%3A%2F%2Fexample.com%2Fa%3Fb%3Dc, which is a single opaque string — a browser treats it as a relative path, and a server routes it nowhere. It is the most common cause of "the link works locally but 404s in production" when URLs are built by concatenation.
How to avoid it: Escape the pieces, not the whole. Encode each parameter value with component mode on, then join them with the literal ? & and = yourself. If you already hold a complete URL and only want to make it legal, uncheck component mode so the reserved set survives. When encoding a URL to pass as a parameter of another URL (a redirect_uri, for example), component mode is correct — that is the one case where the escaped form is what you want.
Encoding a value that is already encoded
Why it happens: Percent signs are themselves escaped, so a second pass turns %20 into %2520 and %2F into %252F. The receiving system decodes once, hands your code the literal text "%20", and the value silently arrives wrong — file names grow visible escapes, and signature checks fail with no useful message. Framework helpers that encode automatically make this easy to do twice.
How to avoid it: Track whether a string is raw or encoded at every boundary, and encode exactly once, as late as possible — at the point the URL is assembled. Check for a literal % followed by two hex digits before encoding again. If you already have a double-encoded value, decode it repeatedly here until the output stops changing, then re-encode once from the clean text.
Assuming + means space everywhere
Why it happens: + only means space in application/x-www-form-urlencoded data — form submissions and, by convention, some query strings. In a path, a fragment, or any other part of a URL, + is a literal plus sign, and RFC 3986 never assigns it that meaning. Decoders disagree accordingly: this tool passes + through unchanged, while a form-data parser would turn it into a space. That mismatch is why addresses like user+tag@example.com arrive with the tag stripped.
How to avoid it: Use %20 for a space anywhere in a URL; it is valid in both contexts. Encode a literal plus as %2B whenever the value might be read by a form parser. If you are decoding form-encoded data specifically, replace + with a space yourself before decoding, and use the Query Parser tool when you want form-style semantics applied for you.
Decoding with a different charset than was used to encode
Why it happens: Percent escapes carry bytes, not characters, and nothing in the string records which charset produced them. Reading UTF-8 escapes as ISO-8859-1 turns Grüße into Grüße (each byte becomes its own character); reading Latin-1 escapes as UTF-8 yields replacement characters instead, because the byte sequence is not valid UTF-8. Both look like corruption but have opposite fixes.
How to avoid it: Default to UTF-8 and only deviate when the other system documents otherwise. When you inherit a broken string, decode it here in one charset, then the other — whichever produces sensible text tells you the original encoding. Then re-encode as UTF-8 and, where you control it, declare the charset explicitly (Content-Type: …; charset=utf-8) so the next consumer does not have to guess.
Escaping characters that should stay literal in a signature
Why it happens: Signing schemes are exact about their safe sets. OAuth 1.0a requires that only A–Z a–z 0–9 - . _ ~ remain unescaped, so ! * ' ( ) must be escaped — the opposite of what encodeURIComponent leaves alone. Libraries that use the built-in produce a signature base string that differs by a few characters and get rejected with an unhelpful "invalid signature".
How to avoid it: Read the provider's encoding rules before signing and compare them against the safe sets listed in the technical reference above. Encode here, then manually escape any of ! * ' ( ) the scheme requires (%21 %2A %27 %28 %29). Verify by reproducing a known-good signature from the provider's own documentation example before debugging your own request.
Frequently asked questions
What is the difference between encodeURI() and encodeURIComponent()?
They differ only in which characters they leave alone. encodeURIComponent escapes everything except A–Z a–z 0–9 and - _ . ! ~ * ' ( ), including : / ? # & = +, so it is the right choice for one parameter value or path segment. encodeURI additionally preserves the reserved set ; , / ? : @ & = + $ #, so it can be applied to a complete URL without destroying its structure — it is really a "make this URL legal" helper. In this tool, component mode on is encodeURIComponent and component mode off is encodeURI. Neither is a security boundary on its own: also escape for the destination context (HTML, SQL, shell) as appropriate.
Should a space be %20 or +?
Use %20. It is valid everywhere in a URL and is what RFC 3986 defines. The + convention comes from application/x-www-form-urlencoded, the HTML form serialisation format, and it only applies to form bodies and query strings that follow that format. Because the two conventions coexist, a + you meant literally can arrive as a space, so encode a literal plus as %2B. Decoders behave differently too: this tool leaves + untouched, while a form parser converts it — worth remembering when a decoded value looks almost right.
Why does one character become several %XX escapes?
Percent-encoding escapes bytes, not characters. In UTF-8 a Latin letter with an accent takes two bytes, most CJK characters take three, and emoji take four, so each character produces that many escapes: 世 is %E4%B8%96 and 🌍 is %F0%9F%8C%8D. Encoding the same text as a single-byte charset like ISO-8859-1 gives one escape per character (ü becomes %FC), which is shorter but cannot represent characters outside that code page — this tool will tell you which character failed rather than corrupting it.
Which characters never need encoding?
The unreserved set: A–Z, a–z, 0–9, hyphen, period, underscore and tilde. RFC 3986 states that percent-encoding or decoding these does not change what a URL means, so normalisers are free to unescape them — encoding them adds length for nothing. Everything else depends on position: the reserved characters : / ? # [ ] @ ! $ & ' ( ) * + , ; = are delimiters and must be escaped when they appear inside a value rather than acting as separators.
Is URL encoding a form of encryption or the same as Base64?
No to both. Percent-encoding is a reversible, key-less transport format: anyone can decode it, and it hides nothing. Base64 is also reversible but solves a different problem — packing arbitrary binary into 64 safe text characters, expanding data by about a third. They are often combined: Base64 output contains + / and =, all of which need percent-encoding before it can travel in a query string, which is why Base64URL (using - and _) exists. For confidentiality, use TLS and real encryption, and keep secrets out of URLs, since URLs are logged, cached and sent in Referer headers.
Can I put non-ASCII characters straight into a URL?
In a browser address bar, yes in appearance only — the browser percent-encodes the path and query as UTF-8 before sending, and converts non-ASCII host names to Punycode (xn--…). Programmatically you should encode explicitly: HTTP request lines must be ASCII, and many servers, proxies, and HTTP clients reject or mangle raw bytes above 0x7F. Encode the path and query here, and use the Punycode tool for internationalised domain names, which follow different rules.
Why do I get "Malformed URI sequence" when decoding?
The input contains a % that is not followed by two valid hex digits — usually a literal percent sign from text like "50% off" that was never encoded, a truncated escape at the end of a copied string, or a value that was cut to a length limit mid-escape. Fix the source by encoding literal percent signs as %25. If you only need to read the value, remove or repair the offending escape; the rest of the string decodes normally.
References
Privacy and availability
- Runs entirely in your browser — zero server processing
- No signup or account required
- Works offline once loaded
- Fast, lightweight, no external dependencies
- Available as a browser extension for Chrome and Firefox