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?
🌍 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