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 href attribute on an <a> element contains a literal pipe character (|), which is not a valid character in a URL according to RFC 3986.
URLs have a defined set of allowed characters. The pipe character (|) is not among them. While most browsers will silently encode the pipe and follow the link anyway, the HTML specification requires that href values contain valid URLs. Characters outside the allowed set must be percent-encoded before being placed in the markup.
The percent-encoded form of | is %7C. Replace every literal | in the URL with %7C to produce a valid href value.
HTML examples
Invalid
<ahref="https://example.com/search?fields=name|date|status">Search</a>
Valid
<ahref="https://example.com/search?fields=name%7Cdate%7Cstatus">Search</a>
A space character in the href attribute of an <a> element is not valid in a URL. Spaces must be encoded as %20 in the query string.
URLs follow the syntax defined in RFC 3986, which does not allow literal space characters anywhere in the URL. When the W3C validator encounters a space in a query string, it flags the href value as malformed. Browsers often handle this gracefully by encoding the space automatically, but the HTML itself is still invalid.
The query component of a URL (everything after the ?) follows the same rule. If a value in the query string contains a space, replace each space with %20. An alternative encoding, +, is specific to the application/x-www-form-urlencoded format used by HTML form submissions, and is also accepted in practice by most servers. However, %20 is the universally correct percent-encoding for a space in any part of a URL.
Invalid example
<ahref="https://example.com/search?query=hello world&lang=en">Search</a>
The space between hello and world causes the validation error.
Valid example
<ahref="https://example.com/search?query=hello%20world&lang=en">Search</a>
Every space in the URL is replaced with %20, and the markup passes validation.
A link element's href attribute contains a character that is not valid in a URL, such as a space, curly brace, or other unencoded special character.
URLs in HTML must conform to the URL Living Standard. Certain characters are not allowed to appear literally in a URL and must be percent-encoded. Common offenders include spaces (use %20), curly braces { } (use %7B %7D), pipe | (use %7C), and angle brackets < > (use %3C %3E).
This error often appears when a template placeholder like {{variable}} is left unresolved in the href value, or when a URL is copied from another context and contains unencoded characters. The validator reads the raw HTML source, so even if a browser might handle a malformed URL gracefully, the markup is still invalid.
To fix it, replace every illegal character with its percent-encoded equivalent, or remove the character if it does not belong in the URL.
Examples
Invalid: unencoded characters in href
<linkrel="stylesheet"href="https://example.com/styles/main file.css">
The space between main and file is not allowed in a URL.
Valid: percent-encoded URL
<linkrel="stylesheet"href="https://example.com/styles/main%20file.css">
If the illegal characters come from a template placeholder that was never processed, remove the placeholder or ensure it resolves before the HTML is served:
Invalid: unresolved template syntax
<linkrel="icon"href="https://example.com/{{icon_path}}">
Valid: resolved or corrected URL
<linkrel="icon"href="https://example.com/images/favicon.ico">
A tel: URI in an href attribute must not contain spaces. The phone number should be written as a continuous string of digits, optionally prefixed with + for the country code.
The tel: URI scheme is defined in RFC 3966. It allows digits, hyphens, dots, and parentheses as visual separators, but spaces are not permitted. Browsers may still dial the number if spaces are present, but the markup is technically invalid.
A common approach is to use the full international number with no spaces in the href value while keeping a human-readable format in the visible link text. If you want visual separators in the href, use hyphens or dots instead of spaces.
Invalid example
<ahref="tel:+1 555 123 4567">Call us</a>
Valid examples
<ahref="tel:+15551234567">+1 555 123 4567</a>
<ahref="tel:+1-555-123-4567">+1 555 123 4567</a>
The | (pipe) character is not allowed in URLs and must be percent-encoded as %7C in the href attribute of an <a> element.
URLs follow the syntax rules defined in RFC 3986. The pipe character is not among the allowed characters in the query component of a URI. When a URL contains a literal |, browsers will often handle it gracefully, but the HTML is technically invalid. The fix is to replace every | with its percent-encoded equivalent %7C.
This commonly appears when linking to external APIs, legacy systems, or content management platforms that use | as a delimiter in query strings.
HTML examples
Invalid example
<ahref="https://example.com/search?filters=color|size|price">Search</a>
Valid example
<ahref="https://example.com/search?filters=color%7Csize%7Cprice">Search</a>
If the URLs are generated dynamically in JavaScript, encodeURI() or encodeURIComponent() will handle the encoding automatically:
constfilters="color|size|price";
consturl=`https://example.com/search?filters=${encodeURIComponent(filters)}`;
// Result: https://example.com/search?filters=color%7Csize%7Cprice
A URL in an href attribute contains a character that must be percent-encoded before it can appear in a query string.
URLs follow the syntax rules defined in RFC 3986. The query component of a URL (everything after the ?) allows a specific set of characters: unreserved characters (A-Z, a-z, 0-9, -, ., _, ~), sub-delimiters (!, $, &, ', (, ), *, +, ,, ;, =), plus :, @, /, and ?. Characters outside this set, such as {, }, |, ^, [, ], spaces, and non-ASCII characters like é or ñ, are illegal in their raw form and must be percent-encoded.
Percent-encoding replaces each disallowed byte with a % followed by its two-digit hexadecimal value. For example, a space becomes %20, a pipe | becomes %7C, and { becomes %7B.
Common causes of this error include:
- Pasting a URL directly from a browser address bar or CMS that displays decoded characters.
- Using curly braces for template placeholders in URLs without encoding them.
- Including spaces or non-ASCII characters in query parameter values.
HTML examples
Invalid: raw illegal characters in the query string
<ahref="https://example.com/search?q=hello world&cat=sci|tech">Search</a>
The space between hello and world and the pipe | between sci and tech are not allowed in a URL query.
Valid: percent-encoded characters
<ahref="https://example.com/search?q=hello%20world&cat=sci%7Ctech">Search</a>
Each illegal character is replaced with its percent-encoded equivalent: space is %20 and | is %7C.
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, orurllib.parse.quote()in Python.
Examples
❌ Incorrect: Unencoded pipe character in query string
<ahref="https://example.com/search?filter=red|blue">Search</a>
✅ Correct: Pipe character percent-encoded as %7C
<ahref="https://example.com/search?filter=red%7Cblue">Search</a>
❌ Incorrect: Unencoded square brackets in query string
<ahref="https://example.com/api?items[0]=apple&items[1]=banana">View items</a>
✅ Correct: Square brackets percent-encoded
<ahref="https://example.com/api?items%5B0%5D=apple&items%5B1%5D=banana">View items</a>
❌ Incorrect: Unencoded space in query string
<ahref="https://example.com/search?q=hello world">Search</a>
✅ Correct: Space encoded as %20
<ahref="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:
constquery="red|blue";
consturl=`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
hrefvalue, 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
hrefvalues contain valid URLs. A tab in the domain makes the URL syntactically invalid. - Accessibility: Screen readers and assistive technologies parse
hrefvalues 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
hrefvalues. In many editors, you can use a regex search for\twithin 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 -->
<ahref="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
<ahref="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:
<ahref="https:// example.com/page">Visit Example</a>
example.com/page
✅ Correct: URL on a single line with no embedded whitespace
<ahref="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
consturl=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) |
[ (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
hrefmakes 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:
<linkrel="stylesheet"href="https://fonts.googleapis.com/css?family=Open+Sans|Roboto">
✅ Pipe character percent-encoded
<linkrel="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:
<linkrel="stylesheet"href="https://example.com/styles?themes[]=dark&themes[]=compact">
✅ Square brackets percent-encoded
<linkrel="stylesheet"href="https://example.com/styles?themes%5B%5D=dark&themes%5B%5D=compact">
❌ Space character in the query string
<linkrel="stylesheet"href="https://example.com/css?file=my styles.css">
✅ Space character percent-encoded
<linkrel="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
<imgsrc="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
<imgsrc="https://example.com/image?filter=red%7Cblue"alt="Filtered image">
❌ Incorrect: unencoded square brackets in query string
<imgsrc="https://example.com/image?size[width]=300&size[height]=200"alt="Resized image">
The [ and ] characters must be encoded.
✅ Correct: square brackets percent-encoded
<imgsrc="https://example.com/image?size%5Bwidth%5D=300&size%5Bheight%5D=200"alt="Resized image">
❌ Incorrect: space in query string
<imgsrc="https://example.com/image?caption=hello world"alt="Captioned image">
✅ Correct: space percent-encoded
<imgsrc="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:
constfilter="red|blue";
consturl=`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.
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.
Pro Trial
Full Pro access. Cancel anytime.
Start Pro Trial →Join teams across 40+ countries