%25 is a percent sign
%25 is a percent sign.
| Character | "%" |
|---|---|
| Name | Percent Sign |
| Encoded | %25 |
| Reserved | No |
Why it breaks things
A percent sign is not just data in a URL — it is the character that introduces an escape sequence. %20 means take the next two characters as hexadecimal and turn them into the byte they represent, a space. Because % already has a job, a literal percent sign has to be written as %25, or a decoder reads it as the start of an escape instead of a character on its own.
This is also the root of double encoding. If a value is already encoded once and something encodes it again by mistake, every % in the string gets encoded a second time into %25. A space, first encoded as %20, becomes %2520 after a second pass. A value that has gone through this twice needs decoding twice to get back to the original text.
The everyday case is ordinary text with a percent sign in it: 50% off, or 100% cotton. Left unencoded, the % is followed by a space, which is not a valid hex digit, so decodeURIComponent does not guess what was meant — it throws a URIError instead. Writing it as 50%25%20off avoids the crash entirely.
Real examples
Without encoding
https://example.com/products?discount=50% off
With encoding
https://example.com/products?discount=50%25%20off
The % is followed by a space, which is not a valid hex digit. decodeURIComponent throws a URIError instead of returning the discount text, rather than silently getting it wrong.
Without encoding
https://example.com/search?q=100%2525%2520cotton
With encoding
https://example.com/search?q=100%25%20cotton
This value has been encoded twice. The first pass correctly turned % into %25 and the space into %20; a second, unwanted pass then encoded those percent signs again, into %2525 and %2520. It now needs decoding twice to read as '100% cotton'.
Decode something
Result
Breakdown
| Part | Value | Copy |
|---|
History
Nothing yet.
History stays in this browser. It is never sent to our server.
Common questions
- What is double encoding and how do I recognize it?
- It happens when a value is run through a URL encoder twice, often because two different parts of the same system both try to encode it. The tell is %25 followed by more escape-looking text, like %2520 — that is what %20 looks like after being encoded a second time.
- Why does my app crash with 'URI malformed' when someone types a percent sign?
- A % has to be followed by exactly two valid hex digits to be a real escape sequence. If it is followed by anything else, like a space or a letter outside a-f, decodeURIComponent cannot make sense of it and throws rather than guessing.
- Is it safe to encode a URL twice, just to be careful?
- No. Encoding an already-encoded URL turns every existing % into %25, which changes the meaning of every escape sequence already in the string. It has to be decoded exactly as many times as it was encoded, not once.
- How do I fix a value that has been double-encoded?
- Run it through a decoder twice, or better, find and fix the code that is encoding it a second time. Decoding twice is a workaround, not a real fix, since the same double-encoding will happen again next time.