Skip to main content
HTML Validation

Bad value for attribute “href” on element “a”: Illegal character in fragment: “#” is not allowed.

About This HTML Issue

In a URL, the # character has a special role: it acts as the delimiter that separates the main URL from the fragment identifier. The fragment typically points to a specific section or element within the target document, often corresponding to an element’s id attribute. Because # serves this reserved purpose, it cannot appear more than once in its raw form within a URL. When the validator encounters something like ##pricing or section#one#two, it flags the extra # characters as illegal.

This issue usually arises from one of these common scenarios:

  • Typos — accidentally typing ## instead of #.
  • String concatenation bugs — building URLs programmatically where a # is included both in the base URL and prepended to the fragment value.
  • Copy-paste errors — duplicating the # when copying URLs from browser address bars or other sources.
  • Literal # intended in fragment — if you genuinely need a # symbol within the fragment text, it must be percent-encoded as %23.

This matters because browsers may handle malformed URLs inconsistently. Some browsers silently strip the extra #, while others may fail to navigate to the intended fragment. Malformed URLs also cause problems for assistive technologies, web crawlers, and any tooling that parses links. Keeping your URLs well-formed ensures predictable behavior across all user agents and complies with the URL Standard and HTML specification.

Examples

Incorrect: duplicate # in the URL

The double ## makes the fragment identifier invalid:

<a href="https://example.com/faqs##pricing">Pricing</a>

Correct: single # delimiter

Remove the extra # so that pricing is the fragment:

<a href="https://example.com/faqs#pricing">Pricing</a>

Incorrect: extra # inside the fragment

Here, the fragment portion overview#details contains a raw #, which is not allowed:

<a href="/docs#overview#details">Details</a>

Correct: percent-encode the literal #

If you truly need a # as part of the fragment text, encode it as %23:

<a href="/docs#overview%23details">Details</a>

In most cases though, this pattern suggests the URL structure should be rethought. A cleaner approach is to link directly to the intended fragment:

<a href="/docs#details">Details</a>

Incorrect: programmatic concatenation error

A common bug in templates or JavaScript is prepending # when the variable already includes it:

<!-- If defined as defined as fragment = "#pricing", this produces a double ## -->

<a href="https://example.com/faqs#pricing">Pricing</a>

Correct: ensure only one # is present

Make sure either the base URL or the fragment variable includes the #, but not both:

<a href="https://example.com/faqs#pricing">Pricing</a>

Fragment-only links

Fragment-only links (links to sections within the same page) follow the same rule — only one #:

<!-- Incorrect -->

<a href="##contact">Contact Us</a>

<!-- Correct -->

<a href="#contact">Contact Us</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?

Ready to validate your sites?
Start your free trial today.