About This HTML Issue
Percent-encoding (also called URL encoding) is the mechanism defined by RFC 3986 for representing special or reserved characters in URLs. It works by replacing a character with a % sign followed by two hexadecimal digits that correspond to the character’s byte value. For example, a space becomes %20, an ampersand becomes %26, and a literal percent sign becomes %25. When a browser or parser encounters % in a URL, it expects the next two characters to be valid hexadecimal digits so it can decode them back to the original character.
If the parser finds a % that is not followed by two hexadecimal digits, it cannot decode the sequence, and the URL is considered invalid. The W3C validator flags this as a bad value for the href attribute.
Common causes
-
A literal
%that wasn’t encoded. This is the most frequent cause. For instance, a URL containing a percentage value like50%in a query string — the%must be written as%25. -
Truncated percent-encoded sequences. A sequence like
%2is incomplete because it only has one hex digit instead of two. -
Invalid hex characters after
%. A sequence like%GZis invalid becauseGandZare not hexadecimal digits (valid hex digits are0–9andA–F). - Copy-pasting URLs from non-web sources. URLs pasted from documents, emails, or spreadsheets may contain unencoded special characters.
Why this matters
- Broken links. Browsers may interpret the malformed URL differently than intended, leading users to the wrong page or a 404 error.
-
Standards compliance. The WHATWG URL Standard and the HTML specification require that
hrefvalues contain valid URLs. Malformed URLs violate these standards. - Accessibility. Screen readers and assistive technologies rely on well-formed URLs to provide accurate navigation information to users.
- Interoperability. While some browsers attempt error recovery on malformed URLs, behavior is not guaranteed to be consistent across all browsers and tools.
How to fix it
-
Encode literal
%as%25. If the%is meant to appear as part of the URL’s content (e.g., in a query parameter value), replace it with%25. -
Complete any truncated sequences. If you intended a percent-encoded character like
%20, make sure both hex digits are present. -
Use proper URL encoding functions. In JavaScript, use
encodeURIComponent()for query parameter values. In server-side languages, use the equivalent encoding function (e.g.,urllib.parse.quote()in Python,urlencode()in PHP).
Examples
Literal % not encoded
<!-- ❌ Bad: the % in "48%" is not followed by two hex digits -->
<a href="https://example.com?width=48%">48% width</a>
<!-- ✅ Good: the % is encoded as %25 -->
<a href="https://example.com?width=48%25">48% width</a>
Truncated percent-encoded sequence
<!-- ❌ Bad: %2 is incomplete — it needs two hex digits -->
<a href="https://example.com/path%2file">Download</a>
<!-- ✅ Good: %2F is a complete encoding for "/" -->
<a href="https://example.com/path%2Ffile">Download</a>
Invalid hexadecimal characters
<!-- ❌ Bad: %XY contains non-hexadecimal characters -->
<a href="https://example.com/search?q=%XYdata">Search</a>
<!-- ✅ Good: if the intent was a literal "%XY", encode the % -->
<a href="https://example.com/search?q=%25XYdata">Search</a>
Multiple unencoded % in a URL
<!-- ❌ Bad: both % signs are unencoded -->
<a href="https://example.com?min=10%&max=90%">Range</a>
<!-- ✅ Good: both % signs are properly encoded -->
<a href="https://example.com?min=10%25&max=90%25">Range</a>
Find issues like this automatically
Rocket Validator scans thousands of pages in seconds, detecting HTML issues across your entire site.
Learn more: