URL Encoder & Decoder
Encode and decode URLs. Broken values are pinned to the character that failed, and addresses are broken down into their parts.
What URL encoding does
An address may only contain a subset of ASCII. Non-ASCII text, spaces, and separators like & cannot sit inside a value as-is. Percent-encoding turns those characters into UTF-8 bytes and writes each one as % plus two hex digits — 한 is three bytes, so it becomes %ED%95%9C.
It is not encryption. No key is needed to reverse it, so never use it to hide anything.
The spec is RFC 3986. The characters that never change (unreserved) are only A-Z a-z 0-9 - . _ ~.
Three scopes — what are you putting in
The same character needs different treatment depending on where it goes.
- URL — for a whole address. Separators like
/?&#are kept; only spaces and non-ASCII change. The structure survives - Text — for anything that is not an address. There is no structure to keep, so separators are encoded too. This is the one for a search term that goes after
?q= - Form — what a
<form>sends (application/x-www-form-urlencoded). A space becomes+, not%20
Put https://a.com/검색?q=한 글 through all three and the difference is immediate. Encoded as Text it becomes https%3A%2F%2Fa.com… — no longer an address at all.
The three cannot be ranked by "how much gets encoded". Form follows the URL Standard's serializer rather than RFC 3986, so it keeps a different set — alphanumerics and *-._ only, which leaves out ~.
The RFC 3986 option
encodeURIComponent() inherits a rule from RFC 2396 and leaves five characters alone: ! ' ( ) *. None of them are unreserved under RFC 3986.
Most of the time this causes no trouble. It matters where both sides must produce the exact same string — OAuth 1.0 and AWS signatures hash the encoded string directly, so if one side leaves ( and the other writes %28, the signature does not match.
Turn the option on to encode those five as well.
It tells you where it broke, and why
The browser's decodeURIComponent() throws a single URIError on failure. It never says where.
This tool separates two cases and pins the character position.
%not followed by two hex digits. Common when an address was truncated somewhere- The bytes are there but they are not valid UTF-8. EUC-KR values surviving in old forum URLs are the classic case —
%C7%D1is "한" in EUC-KR but means nothing in UTF-8
Double-encoded values
You will often meet values like %25EA%25B0%2580, where % itself was wrapped into %25. It happens when code encodes something that was already encoded.
If a decoded value still contains %, the tool says so and offers to decode it again. In the other direction, if you paste an already-encoded value into the encode side, it warns you before you encode it twice.
+ may or may not be a space
Values sent by a form have their spaces turned into +. But the + in a path like C++ is a real plus.
Only whoever produced the value knows which. So the tool does not guess — the checkbox appears only when the value actually contains a +.
Structure
Give it an address or a query string and it breaks it into the parts the spec defines — scheme · host · port · path · query · fragment (RFC 3986 §3). Every value is shown decoded, and each row can be copied on its own.
A bare query string like ?q=…&page=2 works too. Copying just the query is more common than copying a whole address.
While decoding you can also edit a query value and the address above is rebuilt from it. Only the value you touched is re-encoded — every other parameter is left byte for byte as you pasted it. Feeding the whole thing back through URLSearchParams would not do that: it serializes the way the URL spec says a form does, so an untouched a=x~y would come back as a=x%7Ey.