HTML Guides for query
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 W3C HTML Validator checks that URLs used in attributes like href conform to the URL Standard maintained by WHATWG. According to this standard, only certain characters are permitted to appear literally in the query component of a URL. The pipe character (|, Unicode U+007C) is not in the set of allowed query characters, which means it must be percent-encoded as %7C when it appears in a URL’s query string.
While most modern browsers will silently handle a raw | in a URL and still navigate to the intended destination, relying on this behavior is problematic for several reasons:
- Standards compliance: HTML documents that contain unencoded special characters in URLs are technically invalid and will fail W3C validation.
- Interoperability: Not all user agents, HTTP clients, web scrapers, or proxy servers handle illegal URL characters the same way. An unencoded pipe could be misinterpreted, stripped, or cause unexpected behavior in certain environments.
- Security: Properly encoding URLs helps prevent injection attacks and ensures that each part of the URL is unambiguously parsed. Unencoded special characters can be exploited in certain contexts.
- Link sharing and processing: URLs are often copied, pasted, embedded in emails, or processed by APIs. An unencoded | may break the URL when it passes through systems that strictly enforce URL syntax.
This issue commonly arises when URLs are constructed by hand, pulled from databases, or generated by backend systems that don’t automatically encode query parameters. It can also appear when using pipe-delimited values as query parameter values (e.g., ?filter=red|blue|green).
The fix is straightforward: replace every literal | in the URL with its percent-encoded equivalent %7C. If you’re generating URLs in code, use built-in encoding functions like JavaScript’s encodeURIComponent() or PHP’s urlencode() to handle this automatically.
Examples
Incorrect: raw pipe character in query string
<a href="https://example.com/search?q=test|demo">Search</a>
The literal | in the query string triggers the validation error.
Correct: pipe character percent-encoded
<a href="https://example.com/search?q=test%7Cdemo">Search</a>
Replacing | with %7C makes the URL valid. The server receiving this request will decode it back to test|demo automatically.
Incorrect: multiple pipe characters as delimiters
<a href="https://example.com/filter?colors=red|blue|green">Filter colors</a>
Correct: all pipe characters encoded
<a href="https://example.com/filter?colors=red%7Cblue%7Cgreen">Filter colors</a>
Generating encoded URLs in JavaScript
If you’re building URLs dynamically, use encodeURIComponent() to encode individual parameter values:
<script>
const colors = "red|blue|green";
const url = "https://example.com/filter?colors=" + encodeURIComponent(colors);
// Result: "https://example.com/filter?colors=red%7Cblue%7Cgreen"
</script>
This ensures that any special characters in the value — including |, spaces, ampersands, and others — are properly encoded without you needing to remember each character’s percent-encoded form.
Other characters to watch for
The pipe character is not the only one that causes this validation error. Other characters that must be percent-encoded in URL query strings include curly braces ({ and }), the caret (^), backtick (`), and square brackets ([ and ]) when used outside of specific contexts. As a general rule, always encode user-supplied or dynamic values using your language’s URL encoding function rather than constructing query strings through simple string concatenation.
The href attribute expects a valid URL, and URLs follow strict syntax rules defined by RFC 3986. Under these rules, spaces are not permitted anywhere in a URL — not in the path, the query string, the fragment, or any other component. When a browser encounters a space in an href, it may attempt to fix the URL by encoding the space automatically, but this behavior is not guaranteed to be consistent across all browsers and contexts. Relying on browsers to silently correct invalid URLs is fragile and can lead to broken links.
This matters for several reasons. First, standards compliance: the W3C validator flags this because the HTML specification requires href values to be valid URLs. Second, interoperability: while most modern browsers handle spaces gracefully on navigation, other consumers of your HTML — such as web crawlers, screen readers, link checkers, and APIs that parse HTML — may not. Third, accessibility: assistive technologies rely on well-formed URLs to correctly announce and follow links. A malformed URL could lead to unexpected behavior for users depending on these tools.
The fix is straightforward: replace every literal space character with %20. This is called percent-encoding (sometimes called URL encoding). The sequence %20 is the hexadecimal representation of the space character (ASCII code 32). In the query string portion of a URL specifically, you may also see + used to represent spaces (as defined by the application/x-www-form-urlencoded format), but %20 is universally valid across all parts of a URL and is the safer choice.
Be aware that spaces can sometimes be hard to spot, especially trailing spaces or spaces introduced by template engines and CMS platforms that concatenate URL parts. If you’re generating URLs dynamically (e.g., in a server-side template or JavaScript), use built-in encoding functions like encodeURIComponent() in JavaScript or urlencode() in PHP rather than manually replacing spaces.
Examples
Incorrect: space in the query string
<a href="search.html?q=my search">Search for 'my search'</a>
The literal space between my and search makes this an invalid URL.
Correct: space replaced with %20
<a href="search.html?q=my%20search">Search for 'my search'</a>
Incorrect: spaces in the path
<a href="/files/my document.pdf">Download the document</a>
Spaces in the path segment are equally invalid.
Correct: spaces in the path encoded
<a href="/files/my%20document.pdf">Download the document</a>
Incorrect: multiple spaces across path and query
<a href="/product catalog/items?name=red shoes&category=on sale">Red Shoes</a>
Correct: all spaces encoded
<a href="/product%20catalog/items?name=red%20shoes&category=on%20sale">Red Shoes</a>
Note that in addition to encoding the spaces, the & in the query string should be written as & in HTML to avoid being interpreted as the start of an HTML entity.
Using JavaScript to encode URLs dynamically
If you’re building URLs in JavaScript, use encodeURIComponent() for individual parameter values or encodeURI() for full URLs:
<script>
const query = "my search";
const url = "search.html?q=" + encodeURIComponent(query);
// Result: "search.html?q=my%20search"
</script>
This approach prevents encoding issues by handling all special characters automatically — not just spaces, but also characters like #, &, =, and others that have special meaning in URLs.
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.
Ready to validate your sites?
Start your free trial today.