https%3A%2F%2Fshop.example.com%2Fproducts%2Fred%20shoes%3Futm_source%3Dnews%20letter%26q%3Da%2Bb%23reviews- Scheme
- https
- Host
- shop.example.com
- Path
- products / red shoes
- Fragment
- reviews
Percent-encode a value or decode one back, in whichever of the three flavours the destination expects — a query parameter, a whole URL, or form data where a space becomes a plus. Paste a full link and it is broken into its parts, so you can see which piece actually needed escaping.
Step by step
01Paste the value or the link
The direction is detected from the content: something already carrying percent escapes is decoded, anything else is encoded. A full URL is also parsed into its parts so you can see the structure.
02Choose the style the destination expects
Component escapes everything reserved — the right choice for a single parameter value. URI leaves the structural characters intact so a whole link survives. Form matches application/x-www-form-urlencoded, where a space becomes + rather than %20.
03Check the escape count
The number of escapes tells you whether the value was already encoded. A string full of %25 has been encoded twice — a real bug, and the reason a link works in one place and 404s in another.
04Copy the piece you needed
Take the encoded value for the parameter you are building, or the decoded one to read what a system actually received.
Worked example
One value with a space, an ampersand, and a slash in it. Which characters get escaped is the entire difference between the styles — and choosing wrong is how links break.
Given
Component · URI · Form
Component red%20shoes%26socks%2F2
escapes space, &, and / - safe as a value
URI red%20shoes&socks/2
leaves & and / alone - they are structure
Form red+shoes%26socks%2F2
space becomes +, the rest as ComponentURI encoding deliberately leaves & and / untouched because in a whole URL they are structure, not content. Use it on a value and the ampersand ends the parameter early — the server sees red shoes and a mystery parameter called socks/2. Component escapes everything reserved, which is exactly what you want for a value and exactly wrong for a link.
Before you build the URL
Encode the parts, never the whole
Assemble a URL from encoded pieces rather than encoding the assembled string. Encoding at the end either escapes the structural characters and breaks the link, or leaves them and breaks the values — there is no setting that does both jobs at once.
Double encoding is the classic bug
Encode an already-encoded value and % becomes %25, so %20 becomes %2520. The link still looks plausible and the server receives a literal percent sign. If your value is full of %25, something in the chain encoded twice — the escape count here makes that visible immediately.
Plus means space only in form data
In application/x-www-form-urlencoded a space is +, everywhere else it is %20. Decode a query string with the wrong assumption and a genuine plus sign in an email address or a phone number silently becomes a space — which is why +1 555 arrives as 1 555.
The fragment never reaches the server
Everything after # is handled by the browser and is not sent in the request. Putting a value there and expecting the backend to read it is a mistake that survives testing, because the page still works — right up until the server needs the value.
Non-Latin text is UTF-8 first, then escaped
Percent-encoding operates on bytes, so a character outside ASCII becomes several escapes — é is %C3%A9, not one code. That is correct and expected; a value showing é after a round trip has been decoded as Latin-1 somewhere along the way.
Nothing is uploaded
Encoding, decoding, and URL parsing all run in your browser. The links people paste into a tool like this routinely carry session tokens and internal identifiers, so none of it leaves the machine.
The judgement call
Three functions that look interchangeable and are not.
A single query parameter value
Component
Escapes &, =, /, and ? so the value cannot be mistaken for structure. The default for building URLs.
A whole URL you want to keep usable
URI
Leaves the structural characters intact so the link still works, escaping only what is genuinely unsafe.
A POST body or an HTML form
Form
Matches application/x-www-form-urlencoded exactly, plus sign and all.
A path segment containing a slash
Component
An unescaped / becomes a new path segment. Escaping it to %2F is the only way to keep it inside one.
A value that already has % in it
Decode first
Check whether it is already encoded. Encoding again turns %20 into %2520 and the bug travels a long way before anyone notices.
Hiding a value from the user
Wrong tool
Encoding is reversible and visible in the address bar. It obscures nothing from anyone who looks.
Reference
FAQ
Paste the value and use the Component style, which escapes every reserved character — ampersands, equals signs, slashes, and question marks included — so the value cannot be mistaken for URL structure. Build the link from encoded pieces rather than encoding the finished URL.
encodeURI is for a whole URL and deliberately leaves the structural characters (: / ? # & =) intact so the link still works. encodeURIComponent is for a single value and escapes them all. Using the first on a value is how an ampersand inside a search term ends the parameter early.
That is form encoding — application/x-www-form-urlencoded — which is what an HTML form submits. Both are correct in their own context. The problem is decoding: read a query string as form data and a genuine plus, as in a phone number, silently turns into a space.
Encoding an already-encoded value, so % becomes %25 and %20 becomes %2520. The giveaway is a string full of %25. Decode once and look at what you get: if it still contains percent escapes, it was encoded twice and the server is receiving literal percent signs.
Percent-encoding works on bytes, and non-ASCII characters are several bytes in UTF-8 — é encodes to %C3%A9. That is correct. If a round trip produces é instead, something in the chain decoded the bytes as Latin-1 rather than UTF-8.
No. Encoding, decoding, and the URL breakdown all run in your browser. That matters because the links people paste into a tool like this routinely carry session tokens, internal IDs, and campaign parameters.
Encoding, decoding, and URL parsing all run in your browser. Nothing is uploaded or retained, which matters for links carrying tokens and internal identifiers.
Keep going