HTML Guides for illegal character
Learn how to identify and fix common HTML validation errors flagged by the W3C Validator — so your pages are standards-compliant and render correctly across every browser. Also check our Accessibility Guides.
The pipe character | is not permitted in the query component of a URL in the href attribute of an a element.
According to the WHATWG and W3C HTML specifications, URLs in attributes such as href must be valid and properly encoded. The pipe character | is not a valid character in the query string of a URL unless it is percent-encoded as %7C. Failing to encode it will cause validation errors. This is especially important for interoperability and security across browsers and user agents.
Incorrect example (invalid href with pipe):
<a href="https://example.com/search?q=test|demo">Invalid link</a>
Correct example (pipe character encoded):
<a href="https://example.com/search?q=test%7Cdemo">Valid link</a>
Always encode special characters such as | in URLs used within HTML attributes to ensure your documents validate and behave consistently.
The URL standard defines a specific set of characters that are allowed to appear literally in a URL’s query string. Characters outside this allowed set — such as |, [, ], {, }, ^, and unencoded spaces — must be percent-encoded. Percent-encoding replaces the character with a % sign followed by its two-digit hexadecimal ASCII code.
This matters for several reasons. Browsers may handle illegal characters inconsistently — some might silently fix them while others may not, leading to broken links. Screen readers and assistive technologies rely on well-formed URLs to properly announce link destinations. Search engine crawlers may also fail to follow URLs with illegal characters, which can hurt discoverability. Using properly encoded URLs ensures your links work reliably across all user agents and conform to both the HTML and URL specifications.
Common Characters That Need Encoding
Here are frequently encountered characters that trigger this validation error:
| Character | Percent-Encoded |
|---|---|
| (space) | %20 (or + in query strings) |
| | | %7C |
| [ | %5B |
| ] | %5D |
| { | %7B |
| } | %7D |
| ^ | %5E |
Note that characters like ?, =, &, and # have special meaning in URLs and are allowed in their respective positions. For example, ? starts the query string, & separates parameters, and = separates keys from values. However, if these characters appear as part of a parameter’s value (rather than as delimiters), they must also be percent-encoded.
How to Fix It
- Identify the illegal character mentioned in the validator’s error message.
- Replace it with its percent-encoded equivalent.
- If you’re generating URLs dynamically with a server-side language, use built-in encoding functions like encodeURIComponent() in JavaScript, urlencode() in PHP, or urllib.parse.quote() in Python.
Examples
❌ Incorrect: Unencoded pipe character in query string
<a href="https://example.com/search?filter=red|blue">Search</a>
✅ Correct: Pipe character percent-encoded as %7C
<a href="https://example.com/search?filter=red%7Cblue">Search</a>
❌ Incorrect: Unencoded square brackets in query string
<a href="https://example.com/api?items[0]=apple&items[1]=banana">View items</a>
✅ Correct: Square brackets percent-encoded
<a href="https://example.com/api?items%5B0%5D=apple&items%5B1%5D=banana">View items</a>
❌ Incorrect: Unencoded space in query string
<a href="https://example.com/search?q=hello world">Search</a>
✅ Correct: Space encoded as %20
<a href="https://example.com/search?q=hello%20world">Search</a>
If you’re building URLs in JavaScript, use encodeURIComponent() on individual parameter values rather than encoding the entire URL. This function handles all characters that need encoding while leaving the URL structure intact:
const query = "red|blue";
const url = `https://example.com/search?filter=${encodeURIComponent(query)}`;
// Result: "https://example.com/search?filter=red%7Cblue"
Avoid using encodeURI() for this purpose, as it does not encode characters like [, ], or | that are illegal in query strings. Always use encodeURIComponent() for encoding individual query parameter names and values.
URLs must conform to the URL Living Standard, which forbids tab characters (U+0009) within the host/domain portion of a URL. While some browsers may silently strip tabs and still navigate to the intended destination, this behavior is not guaranteed and should not be relied upon.
This issue typically arises from one of the following scenarios:
- Copy-paste errors: Copying a URL from a document, email, or spreadsheet that inadvertently includes tab characters.
- Template or build tool formatting: A templating engine or code generator inserting whitespace (including tabs) into a URL string, especially when the URL is constructed across multiple lines.
- Manual typos: Accidentally pressing the Tab key while editing an href value, particularly in editors that don’t visualize whitespace.
Tab characters are invisible in most code editors by default, which makes this error frustrating to track down. Enabling “show whitespace” or “show invisible characters” in your editor can help you spot the offending character.
Why this matters
- Standards compliance: The HTML specification requires that href values contain valid URLs. A tab in the domain makes the URL syntactically invalid.
- Accessibility: Screen readers and assistive technologies parse href values to announce link destinations. An invalid URL can lead to confusing or broken announcements.
- Reliability: While major browsers tend to be forgiving and strip tabs before resolving URLs, some HTTP clients, crawlers, or older browsers may not. This can cause broken links in unexpected contexts like RSS readers, email clients, or web scrapers.
How to fix it
- Enable visible whitespace in your editor to locate tab characters.
- Search for tab characters in your href values. In many editors, you can use a regex search for \t within attribute values.
- Remove the tab characters so the URL is a clean, continuous string with no embedded whitespace.
- If URLs are dynamically generated, inspect the code that builds them to ensure no tabs or other whitespace are concatenated into the domain.
Examples
❌ Incorrect: Tab character in the domain
In the example below, a tab character is embedded within the domain name (represented here as 	 for visibility, though in source code it would be an actual invisible tab):
<!-- The tab between "example" and ".com" causes the error -->
<a href="https://example .com/page">Visit Example</a>
Note: The tab character between example and .com is invisible in most editors but triggers the validation error.
✅ Correct: Clean URL with no whitespace
<a href="https://example.com/page">Visit Example</a>
❌ Incorrect: Tab introduced by multi-line URL construction in a template
This can happen when a URL is broken across lines in a template and tabs are used for indentation:
<a href="https://
example.com/page">Visit Example</a>
✅ Correct: URL on a single line with no embedded whitespace
<a href="https://example.com/page">Visit Example</a>
Tip: Finding hidden tabs
If you’re having trouble locating the tab character, try pasting your href value into a tool that reveals character codes, or run a quick check in your browser’s developer console:
// Check for tabs in a URL string
const url = document.querySelector('a').getAttribute('href');
console.log(url.includes('\t')); // true if a tab is present
console.log(JSON.stringify(url)); // shows \t explicitly in the output
URLs used in HTML attributes must follow the URL Living Standard, which defines a specific set of characters that are allowed in each part of a URL. The query component of a URL — everything after the ? — permits most printable ASCII characters, but certain characters are still considered illegal and must be percent-encoded. When the W3C validator encounters one of these forbidden characters in the href of a <link> element, it raises this error.
Common characters that trigger this issue include:
| Character | Percent-encoded |
|---|
| | (pipe) | %7C | | [ (left bracket) | %5B | | ] (right bracket) | %5D | | { (left brace) | %7B | | } (right brace) | %7D | | ^ (caret) | %5E | | ` (backtick) | %60 | | (space) | %20 |
Why this matters
While many modern browsers are lenient and will silently fix malformed URLs, relying on this behavior is risky. Invalid URLs can cause problems in several ways:
- Inconsistent browser behavior: Not all user agents handle illegal characters the same way, which can lead to broken stylesheets or resources failing to load.
- Interoperability issues: Proxies, CDNs, and other intermediaries may reject or mangle URLs with illegal characters.
- Standards compliance: Valid HTML requires valid URLs in attributes. An illegal character in the href makes the entire document non-conforming.
- Copy-paste and sharing reliability: Malformed URLs are more likely to break when shared across systems, emails, or documentation.
How to fix it
Identify the illegal characters in your URL’s query string and replace each one with its percent-encoded equivalent. If you’re generating URLs programmatically, use a proper URL encoding function (e.g., encodeURIComponent() in JavaScript, urlencode() in PHP, or urllib.parse.quote() in Python) to ensure all special characters are encoded correctly.
Examples
❌ Illegal pipe character in the query string
This is a common pattern seen with Google Fonts URLs that use | to separate font families:
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans|Roboto">
✅ Pipe character percent-encoded
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans%7CRoboto">
❌ Square brackets in the query string
Some APIs or frameworks use bracket notation in query parameters:
<link rel="stylesheet" href="https://example.com/styles?themes[]=dark&themes[]=compact">
✅ Square brackets percent-encoded
<link rel="stylesheet" href="https://example.com/styles?themes%5B%5D=dark&themes%5B%5D=compact">
❌ Space character in the query string
<link rel="stylesheet" href="https://example.com/css?file=my styles.css">
✅ Space character percent-encoded
<link rel="stylesheet" href="https://example.com/css?file=my%20styles.css">
Note that for Google Fonts specifically, the modern API (v2) uses a different URL format that avoids the pipe character altogether. Where possible, consider updating to the latest version of an API rather than just encoding the old URL.
URLs follow a strict syntax defined by the URL Living Standard and RFC 3986. Only a specific set of characters are allowed to appear literally in a URL’s query string. Characters outside this set — such as pipes, square brackets, curly braces, and certain other symbols — must be percent-encoded. Percent-encoding replaces the character with a % sign followed by its two-digit hexadecimal ASCII code.
When the W3C HTML Validator encounters an <img> tag whose src attribute contains an illegal character in the query portion of the URL, it raises this error. The query string is the part of the URL that comes after the ? character.
Why this matters
- Browser inconsistency: While many modern browsers will silently fix malformed URLs, not all browsers or HTTP clients handle illegal characters the same way. Some may misinterpret the URL or fail to load the resource entirely.
- Standards compliance: Valid URLs are a foundational requirement for interoperable web content. Using illegal characters violates both the HTML and URL specifications.
- Interoperability: Automated tools, web crawlers, proxies, and content delivery networks may reject or mangle URLs containing unencoded special characters, leading to broken images.
- Accessibility: Screen readers and assistive technologies rely on valid markup. Malformed URLs can cause unexpected behavior in these tools.
Common illegal characters and their encodings
Here are characters frequently flagged by the validator:
| Character | Percent-encoded |
|---|---|
| | (pipe) | %7C |
| [ | %5B |
| ] | %5D |
| { | %7B |
| } | %7D |
| ^ | %5E |
| ` (backtick) | %60 |
| (space) | %20 |
How to fix it
Identify the illegal characters in the src URL and replace each one with its corresponding percent-encoded value. If you’re generating URLs dynamically with a programming language, use the language’s built-in URL-encoding function (e.g., encodeURI() or encodeURIComponent() in JavaScript, urlencode() in PHP, urllib.parse.quote() in Python).
Examples
❌ Incorrect: unencoded pipe character in query string
<img src="https://example.com/image?filter=red|blue" alt="Filtered image">
The | character is not allowed literally in the query string.
✅ Correct: pipe character percent-encoded
<img src="https://example.com/image?filter=red%7Cblue" alt="Filtered image">
❌ Incorrect: unencoded square brackets in query string
<img src="https://example.com/image?size[width]=300&size[height]=200" alt="Resized image">
The [ and ] characters must be encoded.
✅ Correct: square brackets percent-encoded
<img src="https://example.com/image?size%5Bwidth%5D=300&size%5Bheight%5D=200" alt="Resized image">
❌ Incorrect: space in query string
<img src="https://example.com/image?caption=hello world" alt="Captioned image">
✅ Correct: space percent-encoded
<img src="https://example.com/image?caption=hello%20world" alt="Captioned image">
Encoding URLs dynamically
If your URLs are built in JavaScript, use encodeURIComponent() for individual query parameter values:
const filter = "red|blue";
const url = `https://example.com/image?filter=${encodeURIComponent(filter)}`;
// Result: "https://example.com/image?filter=red%7Cblue"
This ensures that any special characters in user-provided or dynamic values are properly encoded before being placed into the HTML.
Ready to validate your sites?
Start your free trial today.