Skip to main content
HTML Validation

Bad value X for attribute “src” on element “iframe”: Illegal character in fragment: “#” is not allowed.

About This HTML Issue

A URL follows a specific structure defined by RFC 3986. The general format is:

scheme://host/path?query#fragment

The # character serves as the delimiter that introduces the fragment portion of the URL. It may only appear once in this role. Once the parser encounters the first #, everything after it is treated as the fragment identifier. A second # within that fragment is an illegal character because the fragment production in the URL specification does not permit unescaped # characters.

This validation error commonly arises from:

  • Duplicate # characters — e.g., accidentally including two hash marks like /#?param=value#section.
  • Misplaced query strings — putting ?key=value after the # instead of before it. While this may work in some single-page application routers, it results in the query being part of the fragment, and adding another # after that creates an invalid URL.
  • Copy-paste errors — assembling URLs from multiple parts and inadvertently introducing an extra #.

This matters for several reasons. Browsers may handle malformed URLs inconsistently — some may silently truncate or ignore part of the URL, while others may fail to load the resource entirely. The W3C validator flags this because it violates the HTML specification’s requirement that the src attribute contain a valid URL. Invalid URLs can also cause issues with assistive technologies, link sharing, and automated tools that parse your HTML.

How to fix it

  1. Locate all # characters in the URL and determine which one is the intended fragment delimiter.
  2. Remove any duplicate # characters that were added by mistake.
  3. Move query parameters before the fragment — the ?query portion must come before the #fragment in a well-formed URL.
  4. Percent-encode if needed — if a literal # must appear as data within the fragment or query value (not as a delimiter), encode it as %23.

Examples

Incorrect: multiple # characters

The second # inside the fragment is illegal:

<iframe src="https://example.com/#?secret=123#abc"></iframe>

Correct: query before fragment

Move the query string before the # so the URL has a proper structure:

<iframe src="https://example.com/?secret=123#abc"></iframe>

Correct: single fragment, no query

If you only need a fragment identifier, use a single #:

<iframe src="https://example.com/#abc"></iframe>

Correct: percent-encoding a literal # in a value

If the fragment itself must contain a # as data (not as a delimiter), percent-encode it:

<iframe src="https://example.com/?secret=123#color=%23ff0000"></iframe>

Here, %23ff0000 represents the literal string #ff0000 within the fragment value, which is valid because the # is encoded.

Incorrect: hash-based routing with duplicate #

Some single-page app embed URLs use hash-based routing, which can lead to accidental double hashes:

<iframe src="https://app.example.com/#/dashboard#settings"></iframe>

Correct: use a single fragment for the route

Restructure the URL to use a single # with a combined path:

<iframe src="https://app.example.com/#/dashboard/settings"></iframe>

Or, if the application supports it, use standard path-based routing instead:

<iframe src="https://app.example.com/dashboard/settings"></iframe>

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.