HTML Guides for pipe
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.
A | (pipe) character in the fragment portion of a URL is not allowed without percent-encoding it as %7C.
The fragment is the part of a URL that comes after the # symbol. According to RFC 3986, fragments can only contain unreserved characters (A-Z, a-z, 0-9, -, ., _, ~), percent-encoded characters, sub-delimiters (!, $, &, ', (, ), *, +, ,, ;, =), :, @, /, and ?.
The pipe character | is not in any of those sets, so it must be percent-encoded as %7C when used in a URL fragment.
This issue commonly appears when fragment identifiers are auto-generated from headings or content that contains |, such as table-related text or wiki-style page anchors.
Invalid example
<a href="/page#section|intro">Go to section</a>
Valid example
Replace | with its percent-encoded equivalent %7C:
<a href="/page#section%7Cintro">Go to section</a>
If you control the target element's id, a better approach is to remove the pipe character from the id altogether and use only unreserved characters:
<h2 id="section-intro">Section intro</h2>
<a href="/page#section-intro">Go to section</a>
The href value on the <a> element contains a literal | (pipe) character, which is not allowed in a URL path.
The URL standard doesn't list | among the characters a URL can contain, so a pipe in the path has to be written as %7C. Browsers still follow the link, but the markup is invalid.
This usually comes from a CMS or template that builds the path from a page title. A title like "Summer concert | Tickets" uses the pipe as a separator. If the slug function only lowercases the text and turns spaces into hyphens, the | stays and the path ends up as summer-concert-|-tickets. Fix the slug function so it drops anything other than letters, digits and hyphens. The new slug gives the page a new address, so redirect the old URL to it. If the URLs can't change, write the pipe as %7C in the href instead.
When the href is very long, the validator leaves the value out of the message. The cause and the fix are the same.
Invalid example
<a href="/events/42/summer-concert-|-tickets">Summer concert | Tickets</a>
Valid example
Remove the pipe from the slug:
<a href="/events/42/summer-concert-tickets">Summer concert | Tickets</a>
If the URL has to stay the same, percent-encode the pipe:
<a href="/events/42/summer-concert-%7C-tickets">Summer concert | Tickets</a>
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
<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.
A | (pipe) character in a link element's href attribute is not valid in a URL because it is not a legal character in a query string without being percent-encoded.
This error commonly appears when loading multiple Google Fonts in a single <link> tag using the older Google Fonts API v1 syntax, which used the pipe character to separate font families:
fonts.googleapis.com/css?family=Open+Sans|Roboto
The | character must be encoded as %7C to be valid in a URL. However, even with encoding, the Google Fonts API v1 no longer supports loading multiple families this way. The current Google Fonts API v2 (/css2) uses separate family parameters instead.
Bad example
<link rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Open+Sans|Roboto">
Good example
Use the Google Fonts API v2 with separate family parameters:
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Open+Sans&family=Roboto&display=swap">
If you are not using Google Fonts and cannot change the URL structure, percent-encode the pipe character:
<link rel="stylesheet"
href="https://example.com/css?param1=a%7Cparam2=b">
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.
1K Weekly
1,000 monthly checks. Cancel anytime.
Get 1K Weekly →Join teams across 40+ countries