Guias HTML para href
Aprenda como identificar e corrigir erros comuns de validação HTML sinalizados pelo W3C Validator — para que as suas páginas cumpram os padrões e sejam renderizadas corretamente em todos os navegadores. Consulte também o nosso Guias de acessibilidade.
The <link> element defines a relationship between the current document and an external resource — most commonly stylesheets, icons, preloaded assets, or canonical URLs. According to the HTML specification, the element must include at least one of the href or imagesrcset attributes so the browser knows what resource is being linked. A <link> element without either attribute is essentially an empty declaration: it tells the browser about a relationship type (via rel) but provides no actual resource to fetch or reference.
This validation error commonly occurs in a few scenarios:
- Templating or CMS issues: A dynamic template generates a <link> tag but the URL variable is empty or undefined, resulting in a bare element with no href.
- Incomplete code: A developer adds a <link> with a rel attribute intending to fill in the href later but forgets to do so.
- Copy-paste mistakes: Attributes are accidentally removed during editing or refactoring.
Fixing this is important for several reasons. Browsers may ignore the element entirely or behave unpredictably when encountering a <link> with no resource URL. Unnecessary elements without purpose add bloat to the document and can confuse other developers reading the code. Additionally, tools that parse HTML — such as search engine crawlers and assistive technologies — rely on well-formed markup to correctly understand document relationships.
To resolve the issue, add an href attribute pointing to the target resource, use an imagesrcset attribute when providing responsive image sources, or include both when appropriate.
Examples
Invalid: missing both href and imagesrcset
This <link> declares a stylesheet relationship but doesn’t specify where the stylesheet is located:
<link rel="stylesheet">
This preload link has an as attribute but no resource to fetch:
<link rel="preload" as="image" type="image/png">
Fixed: using href
The most common fix is adding an href attribute with a valid URL:
<link rel="stylesheet" href="styles.css">
<link rel="icon" href="favicon.ico">
<link rel="canonical" href="https://example.com/page">
Fixed: using imagesrcset
For responsive image preloading, the imagesrcset attribute specifies multiple image sources at different resolutions. This is valid without href:
<link rel="preload" as="image" type="image/png" imagesrcset="icon-1x.png 1x, icon-2x.png 2x">
Fixed: using both href and imagesrcset
You can combine both attributes. The href serves as a fallback resource while imagesrcset provides responsive alternatives:
<link rel="preload" as="image" href="icon-1x.png" imagesrcset="icon-1x.png 1x, icon-2x.png 2x">
Handling dynamic templates
If your <link> elements are generated dynamically, make sure the element is only rendered when a valid URL is available. For example, in a template, wrap the output in a conditional check rather than outputting an empty <link>:
<!-- Bad: outputs a link even when the URL is empty -->
<link rel="stylesheet" href="">
<!-- Good: only include the element when there's a real URL -->
<link rel="stylesheet" href="styles.css">
Note that href="" resolves to the current page URL and is technically valid syntax (it won’t trigger this specific error), but it’s almost certainly not what you intend. Always ensure the href value points to the correct resource.
Why This Happens
In HTML, certain attributes are boolean and can appear without a value (e.g., disabled, required). The href attribute is not one of them — it expects a valid URL, path, or fragment identifier as its value. When a validator encounters href with no value or an empty value, it raises a warning because the attribute is being used in a way that doesn’t conform to the specification.
Writing <a href> produces a valueless attribute. Writing <a href=""> produces an attribute whose value is an empty string, which resolves to the current page’s URL per the rules of relative URL resolution. Both forms are problematic:
- href without a value: The HTML spec requires href to contain a valid URL. A valueless attribute is ambiguous and was actively dropped by IE7, meaning the element would lose its link behavior entirely in that browser.
- href="": While technically parsed as a relative URL pointing to the current document, this is almost never the developer’s intention. It causes the page to reload or scroll to the top when clicked, which is confusing for users and harmful for accessibility.
The Impact
- Accessibility: Screen readers rely on the href attribute to identify an <a> element as an interactive link. A missing or empty value creates confusion — the screen reader may announce it as a link but provide no destination, or may not treat it as a link at all.
- Browser compatibility: As the validator message notes, IE7 would strip the attribute entirely, meaning the element lost its link semantics and styling. While IE7 is no longer in common use, valueless attributes can still cause edge-case issues in parsers, crawlers, and automated tools.
- Standards compliance: Valid HTML ensures consistent rendering and behavior across browsers, assistive technologies, and search engine crawlers.
How to Fix It
The fix depends on your intent:
- If the element should link somewhere, provide a real URL: href="https://example.com" or href="/about".
- If the element is a placeholder link (e.g., during development or for JavaScript-driven actions), use href="#" and prevent the default navigation with JavaScript.
- If the element doesn’t need to be a link at all, use a <button> for interactive actions or a <span> for non-interactive text. This is often the most semantically correct choice.
Examples
❌ Incorrect: href without a value
<a href>Click here</a>
This triggers the validation warning. The attribute has no value, which is invalid for href.
❌ Incorrect: href with an empty string
<a href="">Click here</a>
This resolves to the current page URL, likely causing an unintended page reload.
✅ Correct: Provide a real URL
<a href="https://example.com">Visit Example</a>
✅ Correct: Use a fragment as a placeholder
<a href="#" onclick="doSomething(); return false;">Perform action</a>
The return false prevents the page from scrolling to the top. A better modern approach uses event.preventDefault():
<a href="#" id="action-link">Perform action</a>
<script>
document.getElementById("action-link").addEventListener("click", function (e) {
e.preventDefault();
doSomething();
});
</script>
✅ Correct: Use a <button> for actions
If the element triggers a JavaScript action rather than navigating somewhere, a <button> is the most semantically appropriate choice:
<button type="button" onclick="doSomething();">Perform action</button>
Buttons are natively focusable, keyboard-accessible, and clearly communicate interactive intent to assistive technologies — no href needed.
✅ Correct: Use a <span> for non-interactive text
If the element is purely visual and shouldn’t be interactive at all:
<span class="label">Not a link</span>
This removes any expectation of interactivity for both the browser and the user.
When you write a phone link using <a href="callto:...">, you may encounter two distinct problems at once. First, the callto: scheme is a legacy, non-standard protocol originally associated with Skype. The correct and widely supported URI scheme for telephone links is tel:, as defined by RFC 3966. Second, spaces within URI scheme data are illegal characters. URIs must not contain unencoded spaces anywhere, and telephone URIs specifically expect a compact phone number composed of digits, hyphens (-), dots (.), and an optional leading plus sign (+) for international dialing.
The W3C validator raises this error because the value provided to href violates URI syntax rules. Browsers may still attempt to handle the link, but behavior will be inconsistent — some mobile browsers may not recognize callto: at all, and spaces in the URI can cause the number to be parsed incorrectly or truncated. Using the standard tel: scheme with a properly formatted number ensures the link works reliably across devices and platforms, including mobile phones, VoIP applications, and assistive technologies.
How to fix it
- Replace callto: with tel: — The tel: scheme is the standard for phone number links and is supported by all modern browsers and mobile operating systems.
- Remove spaces and slashes — Strip out any spaces, slashes, or parentheses from the phone number. These characters are not valid in a tel: URI without percent-encoding, and they serve no functional purpose in the link target.
- Use a leading + for international numbers — If applicable, include the full international dialing code prefixed with + (e.g., +1 for the US, +49 for Germany). This makes the link work regardless of the caller’s location.
- Optional visual separators — If you want visual separators within the href for readability in your source code, use hyphens (-) or dots (.), which are permitted in tel: URIs. However, the simplest and safest approach is digits only (plus the optional leading +).
Examples
Incorrect: callto: with spaces and slashes
This triggers the validator error because spaces and slashes are illegal in URI scheme data, and callto: is non-standard.
<a href="callto:07142/ 12 34 5">Call us</a>
Incorrect: tel: with spaces
Even with the correct tel: scheme, spaces in the phone number are still invalid URI characters.
<a href="tel:07142 12 34 5">Call us</a>
Correct: tel: with digits only
<a href="tel:0714212345">Call us</a>
Correct: International number with + prefix
<a href="tel:+490714212345">Call us</a>
Correct: Using hyphens for readability
Hyphens are valid characters in tel: URIs and can improve source code readability without affecting functionality.
<a href="tel:+49-07142-12345">Call us</a>
Displaying a formatted number to the user
You can still show a human-friendly formatted number as the visible link text while keeping the href value clean and valid.
<a href="tel:+490714212345">+49 (0) 7142 / 12 34 5</a>
This approach gives you the best of both worlds: the link text is easy for users to read, and the href value is a valid, standards-compliant tel: URI that works reliably across all devices and passes W3C validation.
In a URL, the # character has a special role: it acts as the delimiter that separates the main URL from the fragment identifier. The fragment typically points to a specific section or element within the target document, often corresponding to an element’s id attribute. Because # serves this reserved purpose, it cannot appear more than once in its raw form within a URL. When the validator encounters something like ##pricing or section#one#two, it flags the extra # characters as illegal.
This issue usually arises from one of these common scenarios:
- Typos — accidentally typing ## instead of #.
- String concatenation bugs — building URLs programmatically where a # is included both in the base URL and prepended to the fragment value.
- Copy-paste errors — duplicating the # when copying URLs from browser address bars or other sources.
- Literal # intended in fragment — if you genuinely need a # symbol within the fragment text, it must be percent-encoded as %23.
This matters because browsers may handle malformed URLs inconsistently. Some browsers silently strip the extra #, while others may fail to navigate to the intended fragment. Malformed URLs also cause problems for assistive technologies, web crawlers, and any tooling that parses links. Keeping your URLs well-formed ensures predictable behavior across all user agents and complies with the URL Standard and HTML specification.
Examples
Incorrect: duplicate # in the URL
The double ## makes the fragment identifier invalid:
<a href="https://example.com/faqs##pricing">Pricing</a>
Correct: single # delimiter
Remove the extra # so that pricing is the fragment:
<a href="https://example.com/faqs#pricing">Pricing</a>
Incorrect: extra # inside the fragment
Here, the fragment portion overview#details contains a raw #, which is not allowed:
<a href="/docs#overview#details">Details</a>
Correct: percent-encode the literal #
If you truly need a # as part of the fragment text, encode it as %23:
<a href="/docs#overview%23details">Details</a>
In most cases though, this pattern suggests the URL structure should be rethought. A cleaner approach is to link directly to the intended fragment:
<a href="/docs#details">Details</a>
Incorrect: programmatic concatenation error
A common bug in templates or JavaScript is prepending # when the variable already includes it:
<!-- If defined as defined as fragment = "#pricing", this produces a double ## -->
<a href="https://example.com/faqs#pricing">Pricing</a>
Correct: ensure only one # is present
Make sure either the base URL or the fragment variable includes the #, but not both:
<a href="https://example.com/faqs#pricing">Pricing</a>
Fragment-only links
Fragment-only links (links to sections within the same page) follow the same rule — only one #:
<!-- Incorrect -->
<a href="##contact">Contact Us</a>
<!-- Correct -->
<a href="#contact">Contact Us</a>
A URL fragment identifier is the part of a URL that follows the # character. It typically points to an element on the page that has a matching id attribute. According to the URL specification, certain characters — including spaces — are not allowed to appear literally in a URL. When the W3C HTML Validator encounters a raw space in a fragment, it reports this as an illegal character.
This issue matters for several reasons. Browsers may handle unescaped spaces in fragments inconsistently, leading to broken in-page navigation. Screen readers and other assistive technologies rely on well-formed URLs to navigate users to the correct section of a page. Additionally, spaces in id attributes are themselves invalid in HTML — the id attribute must not contain any ASCII whitespace characters. So the root cause often involves two separate violations: an invalid id and an invalid fragment URL.
The best approach is to use hyphens (-) or underscores (_) instead of spaces in your id values, then match the fragment accordingly. This produces clean, readable, and shareable URLs (e.g., page.html#contact-info instead of page.html#contact%20info). If you’re working with a CMS or build tool that auto-generates id values with spaces, configure it to produce hyphen-separated, lowercase identifiers instead.
If you absolutely cannot change the id values (e.g., they’re generated by a third-party system), you can percent-encode the spaces as %20 in the href. This satisfies URL syntax rules, but note that an id containing spaces is still invalid HTML on its own. Fixing the id is always the preferred solution.
Examples
Invalid: space in fragment and id
This triggers the validator error because href="#My Section" contains an unescaped space. The id="My Section" is also invalid HTML since id values cannot contain spaces.
<a href="#My Section">Go to section</a>
<h2 id="My Section">My Section</h2>
Fixed: hyphen-separated fragment and id
Replace spaces with hyphens in both the id and the fragment. This is the cleanest and most widely recommended approach.
<a href="#my-section">Go to section</a>
<h2 id="my-section">My Section</h2>
Fixed: underscore-separated fragment and id
Underscores work equally well if you prefer that convention.
<a href="#my_section">Go to section</a>
<h2 id="my_section">My Section</h2>
Alternative: percent-encoding the space
Encoding the space as %20 resolves the fragment URL error, but the id with a space is still invalid HTML. Use this only as a last resort when you cannot control the id values.
<a href="#My%20Section">Go to section</a>
<!-- Note: this id is still invalid HTML due to the space -->
<h2 id="My Section">My Section</h2>
Full valid document
A complete example demonstrating multiple in-page links with properly formatted fragments and id values:
<!doctype html>
<html lang="en">
<head>
<title>Page sections</title>
</head>
<body>
<nav>
<ul>
<li><a href="#getting-started">Getting Started</a></li>
<li><a href="#advanced-usage">Advanced Usage</a></li>
<li><a href="#frequently-asked-questions">FAQ</a></li>
</ul>
</nav>
<h2 id="getting-started">Getting Started</h2>
<p>Introduction content here.</p>
<h2 id="advanced-usage">Advanced Usage</h2>
<p>Advanced content here.</p>
<h2 id="frequently-asked-questions">Frequently Asked Questions</h2>
<p>FAQ content here.</p>
</body>
</html>
URLs follow strict syntax rules defined by RFC 3986. Only a specific set of characters are allowed directly in a URL path segment — these include letters, digits, hyphens (-), periods (.), underscores (_), and tildes (~), along with a handful of sub-delimiters like !, $, &, ', (, ), *, +, ,, ;, and =. Any character outside this set — including spaces, angle brackets (< >), curly braces ({ }), pipe characters (|), backslashes (\), carets (^), and backticks (`) — must be percent-encoded.
Percent-encoding replaces the character with a % sign followed by its two-digit hexadecimal ASCII code. For example:
| Character | Percent-encoded |
|---|---|
| (space) | %20 |
| { | %7B |
| } | %7D |
| | | %7C | | < | %3C | | > | %3E | | ^ | %5E |
This validation error matters for several reasons. First, browsers may handle illegal characters inconsistently — some may silently encode them, while others may break the link or navigate to an unexpected destination. Second, tools that parse HTML (screen readers, search engine crawlers, link checkers) rely on well-formed URLs and may fail or behave unpredictably when they encounter illegal characters. Third, standards compliance ensures your HTML works reliably across all environments.
Common causes of this error include:
- Copying and pasting URLs from documents or emails that contain unencoded spaces or special characters.
- Template variables or placeholders left in href values (e.g., {{url}}).
- File paths with spaces used directly as URLs without encoding.
- Non-ASCII characters in URLs that haven’t been properly encoded.
Examples
❌ Space in the URL path
<a href="/my page/about us.html">About Us</a>
✅ Spaces percent-encoded as %20
<a href="/my%20page/about%20us.html">About Us</a>
❌ Curly braces from a template placeholder left in the markup
<a href="/products/{{product-id}}/details">View Details</a>
✅ Curly braces replaced with an actual value
<a href="/products/42/details">View Details</a>
❌ Pipe character in the path
<a href="/search/color|size">Filter Results</a>
✅ Pipe character percent-encoded as %7C
<a href="/search/color%7Csize">Filter Results</a>
❌ Angle brackets in the URL
<a href="/page/<section>">Go to Section</a>
✅ Angle brackets percent-encoded
<a href="/page/%3Csection%3E">Go to Section</a>
How to Fix
- Identify the illegal character from the validator’s error message — it typically tells you exactly which character is problematic.
- Replace it with the correct percent-encoded equivalent using the table above or a URL encoder tool.
- If the URL contains template syntax (like {{...}}), make sure your templating engine processes it before the HTML is served to the browser. The raw template syntax should never appear in the final rendered HTML.
- Consider renaming files and directories to avoid spaces and special characters altogether — this is the cleanest long-term solution.
If you’re generating URLs programmatically, use built-in encoding functions like JavaScript’s encodeURIComponent() or PHP’s rawurlencode() to ensure all special characters are properly escaped before inserting them into href attributes.
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 W3C HTML Validator checks that URLs in href attributes conform to the URL standard (defined by WHATWG). While square brackets are permitted in the host component of a URL (to support IPv6 addresses like [::1]), they are not valid unescaped characters in the query string — the part of the URL that comes after the ?. When the validator encounters a literal [ or ] in the query portion, it flags it as an illegal character.
This issue commonly arises when working with APIs or server-side frameworks that use square brackets in query parameters to represent arrays or nested data structures. For example, PHP-style query strings like ?filter[name]=foo or ?ids[]=1&ids[]=2 contain brackets that must be encoded for valid HTML.
Why this matters
- Standards compliance: The WHATWG URL Standard explicitly lists square brackets among the characters that must be percent-encoded in query strings. Invalid URLs cause W3C validation failures.
- Browser behavior: While most modern browsers are forgiving and will often handle unescaped brackets correctly, relying on this lenient parsing is fragile. Some HTTP clients, proxies, or intermediary servers may reject or mangle URLs with illegal characters.
- Interoperability: Encoded URLs are safer when copied, shared, or processed by tools like link checkers, web scrapers, or email clients that may perform strict URL parsing.
How to fix it
Replace every literal square bracket in the query string with its percent-encoded form:
| Character | Percent-encoded |
|---|---|
| [ | %5B |
| ] | %5D |
If you’re generating URLs dynamically in a server-side language or JavaScript, use the appropriate encoding function (e.g., encodeURIComponent() in JavaScript, urlencode() in PHP, or urllib.parse.quote() in Python) to handle this automatically.
Examples
Incorrect: literal brackets in the query string
<a href="https://example.com/search?filter[status]=active">Active items</a>
This triggers the validation error because [ and ] appear unescaped in the query.
Correct: percent-encoded brackets
<a href="https://example.com/search?filter%5Bstatus%5D=active">Active items</a>
Replacing [ with %5B and ] with %5D resolves the error. The server receiving this request will decode the values back to filter[status]=active.
Incorrect: array-style parameters with brackets
<a href="/api/items?ids[]=1&ids[]=2&ids[]=3">Load items</a>
Correct: array-style parameters encoded
<a href="/api/items?ids%5B%5D=1&ids%5B%5D=2&ids%5B%5D=3">Load items</a>
Note that in addition to encoding the brackets, the & characters in HTML attributes should be written as & for fully valid markup.
Incorrect: brackets in a simple value
<a href="search.html?q=[value]">Search</a>
Correct: encoded brackets in a simple value
<a href="search.html?q=%5Bvalue%5D">Search</a>
Note on brackets in the host (valid use)
Square brackets are valid in the host portion of a URL for IPv6 addresses. The following does not trigger the error:
<a href="http://[::1]:8080/page">IPv6 localhost</a>
The validator only flags brackets that appear in the query string or other parts of the URL where they are not permitted.
The W3C HTML Validator raises this error when it encounters a backslash character (\) inside the href attribute of an anchor element. According to the WHATWG URL Standard, backslashes are not valid characters in URL scheme data. URLs are defined with forward slashes (/) as delimiters — this applies to all parts of a URL, including the scheme, authority, path, query, and fragment.
This issue most commonly occurs when developers copy file paths from Windows operating systems, where backslashes are the default path separator (e.g., C:\Users\Documents\file.html), and paste them directly into HTML markup. It can also happen when server-side code generates URLs using OS-level path functions that produce backslashes on Windows.
Why this matters
- Standards compliance: The WHATWG URL Standard explicitly forbids backslashes in scheme data. Validators flag this as an error because the resulting URL is malformed.
- Cross-browser inconsistency: While some browsers may silently correct backslashes to forward slashes, this behavior is not guaranteed across all browsers or versions. Relying on browser error correction leads to fragile code.
- Broken links: Certain browsers, HTTP clients, or intermediary servers may not auto-correct the backslash, causing the link to fail entirely — resulting in 404 errors or unexpected navigation.
- Security concerns: Backslashes in URLs can be exploited in certain attack vectors like open redirects or path traversal attacks. Using well-formed URLs reduces the attack surface.
How to fix it
- Replace all backslashes (\) with forward slashes (/) in your href values.
- Check for URL generation in server-side code. If your application builds URLs programmatically, ensure it uses forward slashes regardless of the host operating system.
- Use relative or absolute URLs consistently. Whether the URL is relative (images/photo.jpg) or absolute (https://example.com/images/photo.jpg), always use forward slashes.
Examples
Incorrect: backslashes in a relative path
<a href="pages\about\team.html">Meet the Team</a>
Correct: forward slashes in a relative path
<a href="pages/about/team.html">Meet the Team</a>
Incorrect: backslashes in an absolute URL
<a href="https://example.com\blog\2024\post.html">Read the Post</a>
Correct: forward slashes in an absolute URL
<a href="https://example.com/blog/2024/post.html">Read the Post</a>
Incorrect: Windows file path pasted directly
<a href="assets\downloads\report.pdf">Download Report</a>
Correct: converted to a proper relative URL
<a href="assets/downloads/report.pdf">Download Report</a>
Incorrect: mixed slashes
Sometimes a URL contains a mix of forward and backslashes, which also triggers this error:
<a href="https://example.com/images\photos\sunset.jpg">View Photo</a>
Correct: all forward slashes
<a href="https://example.com/images/photos/sunset.jpg">View Photo</a>
A quick way to audit your HTML files is to search for \ within any href (or src, action, etc.) attribute values and replace them with /. In most code editors, you can use find-and-replace scoped to attribute values to handle this efficiently.
URLs follow strict syntax rules defined by RFC 3986. Within the path segment of a URL, only a specific set of characters is allowed: unreserved characters (letters, digits, -, ., _, ~), percent-encoded characters (like %20), and certain reserved sub-delimiters. When the W3C validator encounters a character outside this allowed set in a <link> element’s href attribute, it flags the error.
Common causes of this issue include:
- Template placeholders left in the URL, such as {{variable}} or ${path}, where curly braces and dollar signs haven’t been resolved or encoded.
- Spaces in file paths, such as href="styles/my file.css" instead of using %20 or renaming the file.
- Copy-paste errors that introduce invisible or special Unicode characters.
- Backslashes (\) used instead of forward slashes (/), which is a common mistake on Windows systems.
- Unencoded query-like characters placed in the path portion of the URL.
This matters because browsers may interpret malformed URLs inconsistently. A URL that works in one browser might fail in another. Additionally, invalid URLs can break resource loading, cause accessibility issues when assistive technologies try to process the document, and lead to unexpected behavior with proxies, CDNs, or other intermediaries that strictly parse URLs.
To fix the issue, inspect the href value reported in the error and either:
- Remove the illegal character if it was included by mistake.
- Percent-encode the character if it must be part of the URL (e.g., a space becomes %20, a pipe | becomes %7C).
- Rename the referenced file or directory to avoid special characters altogether (the simplest and most reliable approach).
Examples
Incorrect: Space in the path
<link rel="stylesheet" href="styles/my styles.css">
The space character is not allowed in a URL path segment. The validator will flag this as an illegal character.
Fixed: Percent-encode the space
<link rel="stylesheet" href="styles/my%20styles.css">
Better fix: Rename the file to avoid spaces
<link rel="stylesheet" href="styles/my-styles.css">
Incorrect: Template placeholder left unresolved
<link rel="stylesheet" href="styles/{{theme}}/main.css">
Curly braces { and } are not valid in URL path segments. This commonly happens with server-side or client-side templating syntax that wasn’t processed before the HTML was served.
Fixed: Use a valid resolved path
<link rel="stylesheet" href="styles/dark/main.css">
Incorrect: Backslash used as path separator
<link rel="stylesheet" href="styles\main.css">
Backslashes are not valid URL characters. URLs always use forward slashes.
Fixed: Use forward slashes
<link rel="stylesheet" href="styles/main.css">
Incorrect: Pipe character in the URL
<link rel="stylesheet" href="styles/font|icon.css">
Fixed: Percent-encode the pipe character
<link rel="stylesheet" href="styles/font%7Cicon.css">
Full valid document example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My Webpage</title>
<link rel="stylesheet" href="styles/main.css">
<link rel="icon" href="images/favicon.ico">
</head>
<body>
<h1>Welcome to my webpage!</h1>
<p>Here is some content.</p>
</body>
</html>
When in doubt, run your URL through a URL encoder or validator separately to confirm all characters are legal. As a general best practice, stick to lowercase letters, digits, hyphens, and forward slashes in your file and directory names—this avoids encoding issues entirely and makes your URLs clean and predictable.
The <link> element is used to define relationships between the current document and external resources — most commonly stylesheets, icons, and preloaded assets. The href attribute specifies the URL of that external resource, and it is the core purpose of the element. An empty href attribute makes the <link> element meaningless because there is no resource to fetch or reference.
Why This Is a Problem
Standards compliance: The HTML specification requires the href attribute on <link> to be a valid, non-empty URL. An empty string does not qualify as a valid URL, so the validator flags it as an error.
Unexpected browser behavior: When a browser encounters an empty href, it may resolve it relative to the current document’s URL. This means the browser could end up making an unnecessary HTTP request for the current page itself, interpreting the HTML response as a stylesheet or other resource. This wastes bandwidth, can slow down page loading, and may trigger unexpected rendering issues.
Accessibility and semantics: An empty href provides no useful information to browsers, screen readers, or other user agents about the relationship between the document and an external resource. It adds noise to the DOM without contributing anything functional.
How to Fix It
- Provide a valid URL: If the <link> element is meant to reference a resource, set href to the correct URL of that resource.
- Remove the element: If no resource is needed, remove the entire <link> element rather than leaving it with an empty href.
- Check dynamic rendering: This issue often occurs when a templating engine or CMS outputs a <link> element with a variable that resolves to an empty string. Add a conditional check so the element is only rendered when a valid URL is available.
Examples
❌ Incorrect: Empty href attribute
<link rel="stylesheet" href="">
This triggers the validation error because href is empty.
❌ Incorrect: Empty href from a template
<!-- A template variable resolved to an empty string -->
<link rel="icon" type="image/png" href="">
✅ Correct: Valid href pointing to a resource
<link rel="stylesheet" href="/css/main.css">
✅ Correct: Valid href for a favicon
<link rel="icon" type="image/png" href="/images/favicon.png">
✅ Correct: Remove the element if no resource is needed
<!-- Simply omit the <link> element entirely -->
✅ Correct: Conditional rendering in a template
If you’re using a templating language, wrap the <link> in a conditional so it only renders when a URL is available. For example, in a Jinja2-style template:
{% if stylesheet_url %}
<link rel="stylesheet" href="{{ stylesheet_url }}">
{% endif %}
This ensures the <link> element is never output with an empty href.
When you set href="http://", the browser and the W3C validator attempt to parse this as an absolute URL. According to the URL Standard, a URL with the http or https scheme must include a non-empty host component. The string http:// has the scheme but nothing after the ://, which makes the host empty and the URL invalid.
This issue typically arises when a URL is dynamically generated but the variable or value for the domain is missing, or when a developer uses http:// as a temporary placeholder during development and forgets to replace it.
Why this matters
- Broken navigation: Clicking a link with href="http://" leads to unpredictable behavior. Some browsers may navigate to an error page, while others may interpret it differently.
- Accessibility: Screen readers announce links to users, including their destinations. An invalid URL creates a confusing experience for assistive technology users who expect the link to go somewhere meaningful.
- Standards compliance: The HTML specification requires that href values be valid URLs. An empty host violates the URL parsing rules, causing the W3C validator to flag it as an error.
- SEO: Search engine crawlers may treat invalid URLs as errors, potentially affecting how your site is indexed.
Examples
❌ Invalid: empty host in URL
<a href="http://">Visit our website</a>
This triggers the error because http:// has no host component.
❌ Invalid: same issue with HTTPS
<a href="https://">Secure link</a>
The https scheme also requires a valid host, so this produces the same error.
✅ Fixed: provide a complete URL
<a href="https://example.com">Visit our website</a>
✅ Fixed: use a fragment placeholder if the URL is unknown
If you need a placeholder link during development, use # instead of an incomplete URL:
<a href="#">Visit our website</a>
✅ Fixed: use a relative URL when linking within the same site
<a href="/about">About us</a>
Handling dynamic URLs
If the href value comes from a template or CMS, make sure the variable outputs a complete URL. For example, if a template produces an empty string, you might end up with:
<!-- If {{ site_url }} is empty, this becomes href="http://" -->
<a href="http://{{ site_url }}">Home</a>
Ensure that the variable always resolves to a valid host, or add a fallback so the link is omitted or replaced with a safe default when the value is missing.
A mailto: link follows URI syntax as defined by RFC 3986, which does not permit raw space characters anywhere in the URI. When the W3C validator encounters a space inside the href value of a mailto: link, it reports it as an illegal character in the scheme data. This most commonly happens due to a typo in the email address itself — for example, accidentally inserting a space in the domain name (example .com) or the local part (user name@example.com). It can also occur when query parameters like subject or body contain unencoded spaces.
This matters for several reasons. First, browsers may truncate or misinterpret the href at the space boundary, meaning the mail client may open with an incorrect or incomplete email address. Second, assistive technologies rely on well-formed URIs to communicate link destinations to users. A malformed mailto: link can confuse screen readers or prevent users from understanding where the link leads. Third, invalid markup signals poor quality to search engines and automated tools.
To fix this issue:
- Check the email address for typos. Remove any accidental spaces in the local part (before @) or the domain part (after @).
- Percent-encode spaces in query parameters. If you’re using subject, body, or cc parameters in the mailto: URI, replace spaces with %20.
- Avoid copying and pasting email addresses from formatted documents, which can introduce non-breaking spaces or other invisible whitespace characters.
Examples
Invalid — space in the email address
A space in the domain name makes the URI invalid:
<a href="mailto:user@example com">Send Email</a>
Valid — corrected email address
Remove the space to form a valid email address:
<a href="mailto:user@example.com">Send Email</a>
Invalid — space in the local part
<a href="mailto:john doe@example.com">Send Email</a>
Valid — space removed from local part
<a href="mailto:johndoe@example.com">Send Email</a>
Invalid — unencoded spaces in subject parameter
<a href="mailto:info@example.com?subject=Hello World">Email Us</a>
Valid — percent-encoded spaces in subject parameter
Replace each space with %20 in query parameter values:
<a href="mailto:info@example.com?subject=Hello%20World">Email Us</a>
Valid — full mailto with multiple parameters
<a href="mailto:support@example.com?subject=Bug%20Report&body=Please%20describe%20the%20issue.">
Report a Bug
</a>
A URI (Uniform Resource Identifier) follows a strict syntax defined by RFC 3986. The general structure is scheme:scheme-data, where no spaces or other illegal characters are allowed between the colon and the scheme-specific data. When the W3C validator reports “Illegal character in scheme data,” it means the parser found a character that isn’t permitted in that position of the URI.
The most common cause of this error is adding a space after the colon in tel: links (e.g., tel: +123456789). While browsers may be forgiving and still handle the link, the markup is technically invalid. This matters for several reasons:
- Accessibility: Screen readers and assistive technologies rely on well-formed URIs to correctly identify link types. A malformed tel: link might not be announced as a phone number.
- Standards compliance: Invalid URIs violate the HTML specification, which requires the href attribute to contain a valid URL.
- Cross-device behavior: Mobile devices use the URI scheme to determine which app should handle a link. A malformed tel: URI may fail to trigger the phone dialer on some devices or operating systems.
- Interoperability: While some browsers silently trim spaces, others may encode them as %20, potentially breaking the phone number or other scheme data.
To fix this issue, ensure there are no spaces or other illegal characters between the scheme’s colon and the data that follows it. For telephone links specifically, the number should follow the colon directly, using only digits, hyphens, dots, parentheses, and the + prefix as defined by RFC 3966.
Examples
Incorrect: space after the colon in a tel: link
<a href="tel: +1-234-567-8900">Call us</a>
The space between tel: and +1 is an illegal character in the URI scheme data.
Correct: no space after the colon
<a href="tel:+1-234-567-8900">Call us</a>
Incorrect: space after the colon in a mailto: link
<a href="mailto: support@example.com">Email support</a>
Correct: mailto: with no space
<a href="mailto:support@example.com">Email support</a>
Incorrect: other illegal characters in scheme data
<a href="tel:+1 234 567 8900">Call us</a>
Spaces within the phone number itself are also illegal characters in the URI. Use hyphens, dots, or no separators instead.
Correct: valid separators in a phone number
<a href="tel:+1-234-567-8900">Call us</a>
<a href="tel:+1.234.567.8900">Call us</a>
<a href="tel:+12345678900">Call us</a>
Visual formatting vs. the href value
If you want the displayed phone number to include spaces for readability, format the visible text separately from the href value:
<a href="tel:+12345678900">+1 234 567 8900</a>
The href contains a valid URI with no spaces, while the link text is formatted for easy reading. This gives you the best of both worlds — valid markup and a user-friendly display.
The href attribute on an <a> element must contain a valid URL as defined by the WHATWG URL Standard. According to this standard, the forward slash (/) is the only recognized path segment delimiter. Backslashes (\) have no defined role in URL path syntax and are treated as invalid characters by the validator.
This issue most commonly occurs when developers copy file paths from Windows, which uses backslashes as its native path separator, directly into HTML. For example, copying a path like images\photos\sunset.jpg from Windows Explorer and pasting it into an href attribute will trigger this validation error.
While most modern browsers will silently normalize backslashes to forward slashes, relying on this behavior is problematic for several reasons:
- Standards compliance: Your HTML fails validation, which can mask other real issues in your code.
- Interoperability: Not all HTTP clients, crawlers, or tools normalize backslashes. Search engine bots, link checkers, or older browsers may fail to follow the link correctly.
- Portability: Code that depends on browser error correction is fragile and may break in unexpected environments, such as server-side rendering, email clients, or embedded web views.
- Accessibility: Screen readers and assistive technologies that parse href values may not handle backslashes consistently, potentially breaking navigation for users who rely on these tools.
To fix the issue, simply replace every backslash (\) with a forward slash (/) in any URL used in an href attribute. This applies not only to <a> elements but to any attribute that expects a URL, such as src, action, or data.
Examples
Incorrect: backslash used as path delimiter
<a href="docs\guide\intro.html">Introduction</a>
Correct: forward slash used as path delimiter
<a href="docs/guide/intro.html">Introduction</a>
Incorrect: backslashes in an absolute URL
<a href="https://example.com\blog\2024\post.html">Read the post</a>
Correct: forward slashes in an absolute URL
<a href="https://example.com/blog/2024/post.html">Read the post</a>
Incorrect: mixed slashes
Sometimes a URL contains a mix of forward and backslashes, which still triggers the error:
<a href="assets/images\photo.jpg">View photo</a>
Correct: all forward slashes
<a href="assets/images/photo.jpg">View photo</a>
Tips for avoiding this issue
- Search and replace: If you’re migrating content or working with paths generated on Windows, do a global find-and-replace of \ with / across your HTML files.
- Editor settings: Many code editors can highlight or auto-fix invalid URL characters. Enable linting tools or HTML validation plugins to catch this early.
- Build tools: If your build process generates links from file system paths, ensure it normalizes path separators to forward slashes before writing them into HTML output.
- URL encoding: If you genuinely need a literal backslash character within a URL (which is extremely rare), it must be percent-encoded as %5C. However, this is almost never the intended behavior when this validation error appears.
A valid URL consists of several parts: a scheme (like https), followed by ://, then the host, and optionally a path, query string, and fragment. The :// separator — a colon followed by two forward slashes — is a required part of the URL syntax for schemes like http and https. When one of these slashes is missing, the browser may fail to navigate to the intended destination, interpret the value as a relative path, or behave unpredictably across different environments.
This error commonly occurs due to simple typos, copy-paste mistakes, or programmatic URL construction where string concatenation goes wrong. While some browsers may attempt to correct malformed URLs, you should never rely on this behavior. A malformed href can break navigation entirely, cause security warnings, produce unexpected redirects, or confuse assistive technologies like screen readers that announce link destinations to users.
Beyond the missing-slash case, this error can also appear when other parts of the URL contain characters that aren’t valid without proper encoding — for instance, spaces or special characters that should be percent-encoded. Always ensure your URLs conform to the URL Standard.
How to Fix
- Check the scheme separator: Verify that the protocol is followed by :// (colon and two slashes). For example, https:// not https:/ or https:.
- Validate the full URL: Paste the URL into a browser’s address bar to confirm it resolves correctly.
- Encode special characters: If the URL contains spaces or special characters, use proper percent-encoding (e.g., spaces become %20).
- Review dynamically generated URLs: If URLs are built through string concatenation or template logic, double-check that all parts are joined correctly.
Examples
Incorrect: Missing a slash after the scheme
<a href="https:/example.com">Visit Example</a>
The validator reports this because https:/example.com has only one slash after the colon instead of the required two.
Incorrect: Missing both slashes
<a href="https:example.com">Visit Example</a>
This is also invalid — the colon must be followed by // for https URLs.
Correct: Properly formatted URL
<a href="https://example.com">Visit Example</a>
Correct: URL with a path
<a href="https://example.com/blog/my-post">Read the Post</a>
Correct: URL with encoded spaces
<a href="https://example.com/search?q=hello%20world">Search</a>
Incorrect: Unencoded space in URL
<a href="https://example.com/my page">My Page</a>
Spaces are not valid in URLs. Use %20 or + (in query strings) instead:
<a href="https://example.com/my%20page">My Page</a>
URLs follow a strict syntax defined by RFC 3986 and the URL Living Standard. Only a specific set of characters are allowed to appear unencoded in a URL. Curly braces ({ and }) are among the characters that fall outside this permitted set. When the W3C validator encounters a raw { or } in an href value, it reports the error: Bad value for attribute “href” on element “a”: Illegal character in fragment.
This issue commonly arises in a few scenarios:
- Server-side or client-side template placeholders left unresolved in the rendered HTML (e.g., {id}, {{slug}}).
- URLs copied from API documentation that use curly braces to indicate variable segments (e.g., /users/{userId}/posts).
- Malformed or auto-generated URLs where curly braces were included by mistake.
Why This Matters
Standards compliance: The HTML specification requires that href values conform to valid URL syntax. Curly braces violate this requirement, producing invalid HTML.
Browser inconsistency: While most modern browsers will attempt to handle URLs with illegal characters by silently encoding them, this behavior is not guaranteed across all browsers or versions. Relying on browser error correction can lead to unpredictable results.
Accessibility and interoperability: Assistive technologies, web crawlers, and other tools that parse HTML may not handle illegal URL characters gracefully. Invalid URLs can break link extraction, bookmarking, and sharing functionality.
Debugging difficulty: If curly braces appear in your rendered HTML, it often signals that a template variable was not properly resolved, which may point to a deeper bug in your application logic.
How to Fix It
The fix depends on why the curly braces are there:
-
If the curly braces are literal characters that should be part of the URL, replace them with their percent-encoded equivalents: { becomes %7B and } becomes %7D.
-
If the curly braces are template placeholders (e.g., {userId}), ensure your server-side or client-side code resolves them to actual values before the HTML is sent to the browser. The rendered HTML should never contain unresolved template variables.
-
If the curly braces were included by mistake, simply remove them.
Examples
Incorrect: Raw curly braces in href
<a href="https://example.com/api/users/{userId}/profile">View Profile</a>
This triggers the validation error because { and } are illegal URL characters.
Correct: Percent-encoded curly braces
If the curly braces are meant to be literal parts of the URL:
<a href="https://example.com/api/users/%7BuserId%7D/profile">View Profile</a>
Correct: Resolved template variable
If the curly braces were template placeholders, ensure your templating engine resolves them before rendering. The final HTML should look like:
<a href="https://example.com/api/users/42/profile">View Profile</a>
Incorrect: Curly braces in a fragment identifier
<a href="https://example.com/docs#section-{name}">Jump to Section</a>
Correct: Percent-encoded fragment
<a href="https://example.com/docs#section-%7Bname%7D">Jump to Section</a>
Incorrect: Curly braces in query parameters
<a href="https://example.com/search?filter={active}">Active Items</a>
Correct: Percent-encoded query parameter
<a href="https://example.com/search?filter=%7Bactive%7D">Active Items</a>
Using JavaScript for dynamic URLs
If you need to build URLs dynamically with values that might contain special characters, use encodeURIComponent() in JavaScript rather than inserting raw values into href attributes:
<a id="dynamic-link" href="https://example.com">Dynamic Link</a>
<script>
var value = "{some-value}";
var link = document.getElementById("dynamic-link");
link.href = "https://example.com/path?param=" + encodeURIComponent(value);
</script>
This ensures that any special characters, including curly braces, are automatically percent-encoded in the resulting URL.
A URL fragment identifier is the part of a URL that follows the # symbol, typically used to link to a specific section within a page. The URL specification (RFC 3986 and the WHATWG URL Standard) defines a strict set of characters that are permitted in fragments. The > character (greater-than sign) is among those that are not allowed to appear literally. When the W3C HTML Validator encounters > inside an href value — whether in the fragment or elsewhere in the URL — it raises this error.
In most cases, the > character appears in a URL by accident — for example, from a copy-paste error, a typo where the closing > of the tag accidentally ends up inside the attribute value, or a malformed template expression. Less commonly, a developer may genuinely need the > character as part of the URL content.
Why This Matters
- Broken links: Browsers may interpret the > as the end of the HTML tag or handle the URL unpredictably, leading to broken navigation.
- Standards compliance: Invalid URLs violate both the HTML specification and URL syntax standards, causing validation failures.
- Accessibility: Screen readers and other assistive technologies rely on well-formed markup. A malformed href can confuse these tools and prevent users from reaching the intended destination.
- Interoperability: While some browsers may silently correct or ignore the invalid character, others may not. Valid URLs guarantee consistent behavior everywhere.
How to Fix It
- If the > is a typo or copy-paste error, simply remove it from the href value. This is the most common scenario.
- If the > is intentionally part of the fragment or URL, replace it with its percent-encoded equivalent: %3E.
- Review your templates or CMS output — this error often originates from template engines or content management systems that inject malformed values into href attributes.
Examples
Accidental > in the URL path
A common mistake is accidentally including the tag’s closing > inside the attribute value:
<!-- ❌ Invalid: ">" is not allowed in the URL -->
<a href="/page.php>">Read more</a>
Remove the stray >:
<!-- ✅ Valid: clean URL without illegal character -->
<a href="/page.php">Read more</a>
Illegal > in a fragment identifier
The > can also appear inside the fragment portion of the URL:
<!-- ❌ Invalid: ">" in the fragment -->
<a href="/docs#section->overview">Go to overview</a>
If the > is unintentional, remove it:
<!-- ✅ Valid: fragment without illegal character -->
<a href="/docs#section-overview">Go to overview</a>
If the > is genuinely needed in the fragment, percent-encode it:
<!-- ✅ Valid: ">" encoded as %3E -->
<a href="/docs#section-%3Eoverview">Go to overview</a>
Query string or path containing >
The same rule applies outside of fragments. If > appears anywhere in the URL, encode it:
<!-- ❌ Invalid: ">" in query parameter -->
<a href="/search?filter=price>100">Expensive items</a>
<!-- ✅ Valid: ">" percent-encoded as %3E -->
<a href="/search?filter=price%3E100">Expensive items</a>
Template output errors
If you are using a server-side template or JavaScript framework, ensure that dynamic values inserted into href are properly URL-encoded. For example, in a template that generates links:
<!-- ❌ Invalid: unencoded dynamic value -->
<a href="/results#filter=>50">View results</a>
<!-- ✅ Valid: properly encoded value -->
<a href="/results#filter=%3E50">View results</a>
Most server-side languages provide built-in URL encoding functions (e.g., encodeURIComponent() in JavaScript, urlencode() in PHP, urllib.parse.quote() in Python) that will handle this automatically. Always use these functions when inserting dynamic content into URLs.
A URL can have only one fragment identifier — the portion that comes after the single # symbol. When the browser encounters a # in a URL, it treats everything after it as the fragment. If a second # appears, it becomes an illegal character within that fragment because the fragment portion of a URL does not allow unencoded # characters. This violates the URL specification (WHATWG) and the HTML standard’s requirements for valid URLs in the href attribute.
This matters for several reasons:
- Standards compliance: Browsers may handle malformed URLs inconsistently, leading to unpredictable navigation behavior across different environments.
- Accessibility: Screen readers and assistive technologies rely on well-formed URLs to correctly announce link destinations and allow users to navigate.
- SEO and crawling: Search engine crawlers may fail to follow or index pages with invalid URLs.
The # character is perfectly valid when used exactly once to introduce a fragment. For example, #pricing or /faqs#pricing are fine. The issue arises when a second # appears, such as /faqs#guarantee#pricing, or when # is used in a part of the URL where it isn’t expected.
If you genuinely need a literal # character as part of a path or query string (not as a fragment delimiter), you must percent-encode it as %23.
Examples
❌ Invalid: Multiple # characters in the URL
This triggers the validator error because the fragment (guarantee#pricing) contains an illegal #:
<a href="/faqs#guarantee#pricing">Guarantee and Pricing</a>
✅ Fixed: Use a single fragment identifier
Link to one section at a time with a single #:
<a href="/faqs#guarantee">Guarantee</a>
<a href="/faqs#pricing">Pricing</a>
✅ Fixed: Encode the # if it’s meant as a literal character
If the # is part of the actual path or data (not a fragment delimiter), encode it as %23:
<a href="/faqs%23guarantee#pricing">Pricing</a>
In this case, /faqs%23guarantee is the path (containing a literal #), and pricing is the fragment.
Using fragments correctly in a table of contents
Fragments work well for in-page navigation. Each target element needs a matching id:
<nav>
<ul>
<li><a href="#pricing">Pricing</a></li>
<li><a href="#terms">Terms</a></li>
<li><a href="#guarantee">Guarantee</a></li>
</ul>
</nav>
<h2 id="pricing">Pricing</h2>
<p>All about pricing...</p>
<h2 id="terms">Terms</h2>
<p>You can find our terms at...</p>
<h2 id="guarantee">Guarantee</h2>
<p>We offer a guarantee...</p>
❌ Invalid: # in a query string or path without encoding
Sometimes this error appears when a URL accidentally includes an unencoded # in the wrong place:
<a href="/search?color=#ff0000">Red items</a>
✅ Fixed: Encode the # in the query value
<a href="/search?color=%23ff0000">Red items</a>
Here, %23ff0000 correctly represents the literal string #ff0000 as a query parameter value, rather than being misinterpreted as the start of a fragment.
Common causes
- Copy-pasting URLs from other sources that contain multiple # characters.
- Dynamically generated links where fragment values aren’t properly sanitized.
- Color codes in URLs like #ff0000 that need to be percent-encoded as %23ff0000.
- Concatenation errors in templates where a # is added both in the base URL and the appended fragment.
The fix is always the same: make sure your href contains at most one # used as the fragment delimiter, and percent-encode (%23) any # that is meant as a literal character.
The fragment portion of a URL (everything after the # symbol) follows the same encoding rules as the rest of the URL — literal space characters are not permitted. When a browser encounters a space in a URL fragment, it may try to correct it automatically, but this behavior is not guaranteed across all browsers and contexts. Relying on browser error-correction leads to fragile links that may break unpredictably.
This issue matters for several reasons. First, it produces invalid HTML that fails W3C validation. Second, fragment navigation (jumping to a specific section of a page) may not work correctly if the browser doesn’t auto-correct the space. Third, assistive technologies like screen readers rely on well-formed URLs to announce link destinations accurately. Finally, tools that parse or process HTML programmatically — such as crawlers, link checkers, and content management systems — may misinterpret or reject malformed URLs.
The most common scenario for this error is linking to an id attribute on the same page or another page where the id contains spaces. However, it’s worth noting that id values themselves cannot contain spaces in valid HTML (a space in an id would make it multiple invalid tokens). So if you’re writing both the link and the target, the best fix is often to correct the id itself by using hyphens or underscores instead of spaces.
How to Fix It
There are two main approaches:
- Percent-encode the spaces — Replace each space with %20 in the href value.
- Use space-free identifiers — Change the target id to use hyphens or camelCase, then update the fragment to match.
The second approach is strongly preferred because it fixes the root problem and produces cleaner, more readable markup.
Examples
❌ Invalid: Space in the fragment
<a href="https://example.com/page#some term">Go to section</a>
<a href="#my section">Jump to My Section</a>
✅ Fixed: Percent-encode the space
If you cannot control the target id (e.g., linking to an external page), percent-encode the space:
<a href="https://example.com/page#some%20term">Go to section</a>
✅ Better fix: Use a hyphenated id and matching fragment
When you control both the link and the target, use a space-free id:
<h2 id="my-section">My Section</h2>
<p>Some content here.</p>
<a href="#my-section">Jump to My Section</a>
❌ Invalid: Space in fragment linking to another page
<a href="/docs/getting-started#quick start guide">Quick Start Guide</a>
✅ Fixed: Matching hyphenated id
<!-- On the target page (/docs/getting-started): -->
<h2 id="quick-start-guide">Quick Start Guide</h2>
<!-- On the linking page: -->
<a href="/docs/getting-started#quick-start-guide">Quick Start Guide</a>
A note on id naming conventions
Since fragment identifiers reference id attributes, adopting a consistent id naming convention avoids this issue entirely. Common patterns include:
<!-- Hyphens (most common, used by many static site generators) -->
<section id="getting-started">
<!-- camelCase -->
<section id="gettingStarted">
<!-- Underscores -->
<section id="getting_started">
All three are valid and will never trigger a space-related validation error in your fragment links.
URLs follow strict syntax rules defined by RFC 3986, which does not permit literal space characters anywhere in a URI. When the W3C validator encounters a space in the href attribute of an <a> element — particularly within the query string (the part after the ?) — it flags it as an illegal character.
While most modern browsers will silently fix malformed URLs by encoding spaces for you, relying on this behavior is problematic for several reasons:
- Standards compliance: The HTML specification requires that href values contain valid URLs. A space makes the URL syntactically invalid.
- Interoperability: Not all user agents, crawlers, or HTTP clients handle malformed URLs the same way. Some may truncate the URL at the first space or reject it entirely.
- Accessibility: Screen readers and assistive technologies may struggle to interpret or announce links with invalid URLs.
- Link sharing and copy-pasting: If a user copies the link from the source or if the URL is used in an API or redirect, the unencoded space can cause breakage.
To fix this issue, replace every literal space character in the URL with %20. Within query string values, you can also use + as a space encoding (this is the application/x-www-form-urlencoded format commonly used in form submissions). If you’re generating URLs dynamically, use your programming language’s URL encoding function (e.g., encodeURIComponent() in JavaScript, urlencode() in PHP, or urllib.parse.quote() in Python).
Examples
Incorrect — spaces in the query string
<a href="https://example.com/search?query=hello world&lang=en">Search</a>
The space between hello and world is an illegal character in the URL.
Correct — space encoded as %20
<a href="https://example.com/search?query=hello%20world&lang=en">Search</a>
Correct — space encoded as + in query string
<a href="https://example.com/search?query=hello+world&lang=en">Search</a>
Using + to represent a space is valid within query strings and is commonly seen in URLs generated by HTML forms.
Incorrect — spaces in the path and query
<a href="https://example.com/my folder/page?name=John Doe">Profile</a>
Correct — all spaces properly encoded
<a href="https://example.com/my%20folder/page?name=John%20Doe">Profile</a>
Generating safe URLs in JavaScript
If you’re building URLs dynamically, use encodeURIComponent() for individual parameter values:
<script>
const query = "hello world";
const url = "https://example.com/search?query=" + encodeURIComponent(query);
// Result: "https://example.com/search?query=hello%20world"
</script>
Note that encodeURIComponent() encodes spaces as %20, which is safe for use in any part of a URL. Avoid using encodeURI() for query values, as it does not encode certain characters like & and = that may conflict with query string syntax.
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.
A < character in an href attribute value is not allowed because it is a reserved character in URLs and must be percent-encoded.
The href attribute on an <a> element must contain a valid URL or URL fragment. Characters like <, >, {, }, and others are not permitted directly in URLs according to RFC 3986. The < character is especially problematic because browsers and parsers interpret it as the start of an HTML tag, which can break your markup and introduce security risks like XSS vulnerabilities.
This error commonly appears when template syntax (e.g., {{variable}}), unescaped user input, or malformed URLs end up inside an href value. If you genuinely need a < in a URL, it must be percent-encoded as %3C. Similarly, > should be encoded as %3E.
Example with the issue
<a href="https://example.com/search?q=<value>">Search</a>
How to fix it
Percent-encode the special characters in the URL:
<a href="https://example.com/search?q=%3Cvalue%3E">Search</a>
If you’re generating URLs dynamically on the server side, use your language’s built-in URL encoding function (e.g., encodeURIComponent() in JavaScript, urlencode() in PHP) to ensure all special characters are properly escaped before inserting them into href attributes.
The URL standard (defined by WHATWG) specifies a strict set of characters allowed in each part of a URL. A space character is not among them. When the validator encounters a literal space in an href value, it reports the error “Illegal character in scheme data: space is not allowed.” This applies to spaces anywhere in the URL — the path, query string, fragment, or even after the scheme (e.g., https:).
While most modern browsers are forgiving and will attempt to fix malformed URLs by encoding spaces automatically, relying on this behavior is problematic for several reasons:
- Standards compliance: Invalid URLs violate the HTML specification, and markup that depends on browser error-correction is fragile and unpredictable.
- Accessibility: Assistive technologies, such as screen readers, may not handle malformed URLs the same way browsers do. This can result in broken links for users relying on these tools.
- Interoperability: Non-browser consumers of your HTML — search engine crawlers, link checkers, email clients, RSS readers, and APIs — may not perform the same auto-correction, leading to broken links or missed content.
- Copy-paste and sharing: When users copy a malformed URL from the source, the space can cause the link to break when pasted into other applications.
How to fix it
The fix depends on where the space appears:
- In the path or fragment: Replace each space with %20. For example, /my file.html becomes /my%20file.html.
- In the query string: You can use %20 or, if the value is part of application/x-www-form-urlencoded data, + is also acceptable for spaces within query parameter values. However, %20 is universally safe.
- Programmatically: Use encodeURI() in JavaScript to encode a full URL (it preserves structural characters like /, ?, and #). Use encodeURIComponent() to encode individual query parameter values. On the server side, use your language’s equivalent URL-encoding function.
If you’re writing URLs by hand in HTML, simply find every space and replace it with %20. If URLs are generated dynamically (from a database, CMS, or user input), ensure your templating or server-side code encodes them before inserting into the markup.
Examples
Invalid — space in the path
<a href="https://example.com/docs/My Report.pdf">Download Report</a>
The literal space between “My” and “Report” triggers the validator error.
Fixed — space encoded as %20
<a href="https://example.com/docs/My%20Report.pdf">Download Report</a>
Invalid — space in a query parameter
<a href="https://example.com/search?q=hello world">Search</a>
Fixed — space encoded in the query string
<a href="https://example.com/search?q=hello%20world">Search</a>
Invalid — multiple spaces in different URL parts
<a href="https://example.com/my folder/page two.html?ref=some value#my section">Link</a>
Fixed — all spaces encoded
<a href="https://example.com/my%20folder/page%20two.html?ref=some%20value#my%20section">Link</a>
Encoding URLs with JavaScript
If you’re building URLs dynamically, use the built-in encoding functions rather than doing manual string replacement:
<script>
// encodeURI encodes a full URL but preserves :, /, ?, #, etc.
const url = encodeURI("https://example.com/docs/My Report.pdf");
// Result: "https://example.com/docs/My%20Report.pdf"
// encodeURIComponent encodes a single value (for query params)
const query = encodeURIComponent("hello world");
// Result: "hello%20world"
</script>
Note that encodeURI() is appropriate for encoding a complete URL, while encodeURIComponent() should be used for individual components like query parameter values — it encodes characters such as / and ? that have structural meaning in a URL.
Pronto para validar os seus sites?
Comece o seu teste gratuito hoje.