Skip to main content
HTML Validation

Bad value X for attribute “href” on element “a”: Percentage ("%") is not followed by two hexadecimal digits.

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

  1. A literal % that wasn’t encoded. This is the most frequent cause. For instance, a URL containing a percentage value like 50% in a query string — the % must be written as %25.
  2. Truncated percent-encoded sequences. A sequence like %2 is incomplete because it only has one hex digit instead of two.
  3. Invalid hex characters after %. A sequence like %GZ is invalid because G and Z are not hexadecimal digits (valid hex digits are 09 and AF).
  4. 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 href values 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.

Help us improve our guides

Was this guide helpful?
🌍 Trusted by teams worldwide

Validate at scale.
Ship accessible websites, faster.

Automated HTML & accessibility validation for large sites. Check thousands of pages against WCAG guidelines and W3C standards in minutes, not days.

Scheduled Reports
API Access
Open Source Standards
$7 / 7 days

Pro Trial

Full Pro access. Cancel anytime.

Start Pro Trial →

Join teams across 40+ countries