HTML Guides for href
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.
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%7Band}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
hrefcan 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 thehrefvalue. 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
hrefattributes.
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 # character inside the fragment portion of a URL is not valid and must be percent-encoded as %23.
The fragment identifier in a URL is everything after the first # character. Because # itself is the delimiter that starts the fragment, any additional # characters within the fragment are illegal according to RFC 3986. Browsers may handle these gracefully, but the markup is technically invalid.
This commonly happens when an id value on the target element contains a #, or when a URL is copied from somewhere and pasted without encoding. The fix is to replace any extra # inside the href fragment with %23. Better yet, avoid using # in id values altogether.
Invalid example
<a href="#section#2">Go to section</a>
The fragment section#2 contains a second #, which is not allowed.
Fixed example
Option 1: percent-encode the # inside the fragment.
<a href="#section%232">Go to section</a>
Option 2 (preferred): change the target id so it does not contain # at all.
<h2 id="section-2">Section 2</h2>
<a href="#section-2">Go to section</a>
A backslash (\) is not a valid character in a URL fragment and must be replaced with a forward slash (/) or percent-encoded.
The href attribute on an <a> element must contain a valid URL according to the URL Living Standard. The fragment portion of a URL — the part after the # symbol — follows the same rule: it can contain most characters, but the backslash (\) is explicitly forbidden as a bare character.
This commonly happens when copying file paths from Windows, which uses backslashes as directory separators, and pasting them into an href. Browsers may silently convert \ to /, but the markup is still invalid.
To fix this, replace every \ with / in the URL. If for some reason you actually need a literal backslash in the fragment, percent-encode it as %5C.
HTML Examples
❌ Invalid: backslash in the fragment
<a href="page.html#section\one">Link</a>
✅ Fixed: use a forward slash or percent-encoding
<!-- Option 1: Replace with forward slash -->
<a href="page.html#section/one">Link</a>
<!-- Option 2: Percent-encode the backslash -->
<a href="page.html#section%5Cone">Link</a>
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 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
%20in thehrefvalue. - Use space-free identifiers — Change the target
idto 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.
Spaces in the href attribute of an <a> element are not valid URL characters and must be encoded as %20.
URLs follow the syntax defined in RFC 3986, which does not allow literal space characters in any component of a URI. When a browser encounters a space in an href value, it often silently corrects it, but the HTML is still technically invalid. The W3C validator flags this because the raw space violates the URL specification.
To fix the issue, replace each space in the URL with %20. This is the percent-encoded form of the space character. If the URL points to a local file or path that genuinely contains spaces, the encoding is still required.
Some common situations where this appears:
- Links to files with spaces in their names, like
my document.pdf. - Paths that include folder names with spaces, like
/my folder/page.html. - Query parameters that contain unencoded spaces.
HTML examples
Invalid: space in href
<a href="/my folder/my document.pdf">Download</a>
Valid: spaces encoded as %20
<a href="/my%20folder/my%20document.pdf">Download</a>
If you control the file or directory names, renaming them to avoid spaces altogether is a simpler long term fix. Use hyphens or underscores instead:
<a href="/my-folder/my-document.pdf">Download</a>
Square brackets ([ and ]) are not valid characters in a URL path and must be percent-encoded.
The HTML specification requires that the href attribute on an <a> element contains a valid URL. According to RFC 3986, square brackets are reserved characters that are only permitted in the host component of a URI (specifically for IPv6 addresses like [::1]). When they appear in the path, query, or fragment components, they must be percent-encoded as %5B for [ and %5D for ].
This commonly happens with URLs that contain array-like query parameters (e.g., filter[status]=active) or paths that include brackets for some framework-specific routing convention.
To fix the issue, replace every [ with %5B and every ] with %5D in the URL path or query string.
HTML examples
Invalid: square brackets in the URL
<a href="/products?filter[color]=red&filter[size]=large">
Red, large products
</a>
Valid: percent-encoded square brackets
<a href="/products?filter%5Bcolor%5D=red&filter%5Bsize%5D=large">
Red, large products
</a>
The encoded version is functionally equivalent. Most web servers and frameworks will decode %5B and %5D back to [ and ] automatically when processing the request.
Square brackets ([ and ]) are not valid characters in URLs according to RFC 3986 and must be percent-encoded in the href attribute of <a> elements.
URLs have a strict set of allowed characters. Square brackets are reserved exclusively for IPv6 addresses in the host portion of a URL (e.g., http://[::1]/). Anywhere else in a URL, including query strings, they must be percent-encoded: [ becomes %5B and ] becomes %5D.
This issue commonly appears when linking to URLs that use square brackets in query parameters, a pattern found in some PHP frameworks and APIs (e.g., ?filter[name]=value). While most browsers handle unencoded brackets without problems, the HTML specification requires valid URLs, and the W3C validator flags the violation.
Invalid example
<a href="https://example.com/results?filter[status]=active&filter[role]=admin">
View results
</a>
Valid example
Replace [ with %5B and ] with %5D:
<a href="https://example.com/results?filter%5Bstatus%5D=active&filter%5Brole%5D=admin">
View results
</a>
The browser will decode the percent-encoded characters when sending the request, so the server receives the same query string either way.
The | (pipe) character is not allowed in URLs and must be percent-encoded as %7C in the href attribute of an <a> element.
URLs follow the syntax rules defined in RFC 3986. The pipe character is not among the allowed characters in the query component of a URI. When a URL contains a literal |, browsers will often handle it gracefully, but the HTML is technically invalid. The fix is to replace every | with its percent-encoded equivalent %7C.
This commonly appears when linking to external APIs, legacy systems, or content management platforms that use | as a delimiter in query strings.
HTML examples
Invalid example
<a href="https://example.com/search?filters=color|size|price">Search</a>
Valid example
<a href="https://example.com/search?filters=color%7Csize%7Cprice">Search</a>
If the URLs are generated dynamically in JavaScript, encodeURI() or encodeURIComponent() will handle the encoding automatically:
const filters = "color|size|price";
const url = `https://example.com/search?filters=${encodeURIComponent(filters)}`;
// Result: https://example.com/search?filters=color%7Csize%7Cprice
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
hrefvalues 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.
A URL in an href attribute contains a character that must be percent-encoded before it can appear in a query string.
URLs follow the syntax rules defined in RFC 3986. The query component of a URL (everything after the ?) allows a specific set of characters: unreserved characters (A-Z, a-z, 0-9, -, ., _, ~), sub-delimiters (!, $, &, ', (, ), *, +, ,, ;, =), plus :, @, /, and ?. Characters outside this set, such as {, }, |, ^, [, ], spaces, and non-ASCII characters like é or ñ, are illegal in their raw form and must be percent-encoded.
Percent-encoding replaces each disallowed byte with a % followed by its two-digit hexadecimal value. For example, a space becomes %20, a pipe | becomes %7C, and { becomes %7B.
Common causes of this error include:
- Pasting a URL directly from a browser address bar or CMS that displays decoded characters.
- Using curly braces for template placeholders in URLs without encoding them.
- Including spaces or non-ASCII characters in query parameter values.
HTML examples
Invalid: raw illegal characters in the query string
<a href="https://example.com/search?q=hello world&cat=sci|tech">Search</a>
The space between hello and world and the pipe | between sci and tech are not allowed in a URL query.
Valid: percent-encoded characters
<a href="https://example.com/search?q=hello%20world&cat=sci%7Ctech">Search</a>
Each illegal character is replaced with its percent-encoded equivalent: space is %20 and | is %7C.
The URL standard defines a specific set of characters that are allowed to appear literally in a URL's query string. Characters outside this allowed set — such as |, [, ], {, }, ^, and unencoded spaces — must be percent-encoded. Percent-encoding replaces the character with a % sign followed by its two-digit hexadecimal ASCII code.
This matters for several reasons. Browsers may handle illegal characters inconsistently — some might silently fix them while others may not, leading to broken links. Screen readers and assistive technologies rely on well-formed URLs to properly announce link destinations. Search engine crawlers may also fail to follow URLs with illegal characters, which can hurt discoverability. Using properly encoded URLs ensures your links work reliably across all user agents and conform to both the HTML and URL specifications.
Common Characters That Need Encoding
Here are frequently encountered characters that trigger this validation error:
| Character | Percent-Encoded |
|---|---|
| (space) | %20 (or + in query strings) |
| | %7C |
[ | %5B |
] | %5D |
{ | %7B |
} | %7D |
^ | %5E |
Note that characters like ?, =, &, and # have special meaning in URLs and are allowed in their respective positions. For example, ? starts the query string, & separates parameters, and = separates keys from values. However, if these characters appear as part of a parameter's value (rather than as delimiters), they must also be percent-encoded.
How to Fix It
- Identify the illegal character mentioned in the validator's error message.
- Replace it with its percent-encoded equivalent.
- If you're generating URLs dynamically with a server-side language, use built-in encoding functions like
encodeURIComponent()in JavaScript,urlencode()in PHP, orurllib.parse.quote()in Python.
Examples
❌ Incorrect: Unencoded pipe character in query string
<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.htmlbecomes/my%20file.html. - In the query string: You can use
%20or, if the value is part ofapplication/x-www-form-urlencodeddata,+is also acceptable for spaces within query parameter values. However,%20is universally safe. - Programmatically: Use
encodeURI()in JavaScript to encode a full URL (it preserves structural characters like/,?, and#). UseencodeURIComponent()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.
The W3C HTML Validator checks that URLs provided in href attributes conform to the URL specification. Square brackets ([ and ]) are reserved characters with very specific, limited uses in URLs — they are only permitted in the host portion of a URL to denote IPv6 addresses (e.g., http://[::1]/). When they appear elsewhere, such as in the scheme data, path, or query string without being percent-encoded, the URL is considered malformed.
This commonly happens in a few scenarios:
- Mailto links where someone wraps an email address in brackets, like
mailto:[user@example.com]. - Template variables that haven't been processed, leaving literal bracket syntax (e.g.,
{{,[,]) in the rendered HTML. - Manually constructed URLs where brackets are mistakenly used as part of the path or query string instead of being percent-encoded as
%5Band%5D.
Using invalid URLs can cause browsers to misinterpret the link destination, break navigation, or cause unexpected behavior. Assistive technologies such as screen readers also rely on well-formed URLs to correctly communicate link targets to users. Keeping your URLs standards-compliant ensures consistent, predictable behavior across all browsers and devices.
How to fix it
- Remove unnecessary brackets. If the brackets are not part of the actual data (e.g., decorative brackets around an email address), simply delete them.
- Percent-encode brackets when they are part of the data. If you genuinely need square brackets in a URL's path or query string, encode
[as%5Band]as%5D. - Check your templating engine output. If you use a templating system, inspect the final rendered HTML in a browser to make sure template syntax has been fully replaced with valid values.
Examples
Invalid: square brackets in a mailto URL
The brackets around the email address are not valid URL characters in this context.
<a href="mailto:[user@example.com]">Email Us</a>
Fixed: remove the brackets
<a href="mailto:user@example.com">Email Us</a>
Invalid: square brackets in a query string
<a href="https://example.com/search?filter[status]=active">Search</a>
Fixed: percent-encode the brackets
<a href="https://example.com/search?filter%5Bstatus%5D=active">Search</a>
Invalid: unprocessed template syntax in rendered HTML
If your templating engine fails to replace a variable, the final HTML may contain bracket characters:
<a href="mailto:[% user.email %]">Email Us</a>
Fixed: ensure the template renders a valid URL
Make sure the template variable resolves correctly. The rendered output should look like:
<a href="mailto:user@example.com">Email Us</a>
In your template source, this might be written as:
<a href="mailto:{{ user.email }}">Email Us</a>
The key is that the final HTML delivered to the browser must contain a valid, bracket-free URL (unless the brackets are properly percent-encoded). Always validate your rendered output, not just your template source, to catch issues like this.
A URL is made up of several parts: scheme, host (domain), path, query, and fragment. While some of these parts allow certain special characters (often percent-encoded), the host portion has strict rules. Domain names follow the DNS naming conventions, which only permit ASCII letters (a-z, A-Z), digits (0-9), hyphens (-), and dots (.) as label separators. Spaces are categorically forbidden.
This validation error typically occurs in two scenarios:
- A literal space appears in the domain, e.g.,
http://my domain.com. This is often a typo or a copy-paste error. - A percent-encoded space (
%20) appears in the domain, e.g.,http://my%20domain.com. While%20is valid in URL paths and query strings, it is not valid in the host portion. Percent-encoding does not make a space legal in a domain name — it still resolves to a space character, which DNS cannot handle.
Why this is a problem
- Broken links: Browsers cannot resolve a domain with spaces to an actual server. Users clicking the link will get an error or be taken nowhere.
- Accessibility: Screen readers and assistive technologies may announce the link, but users will encounter a dead end, creating a frustrating experience.
- Standards compliance: The WHATWG URL Standard explicitly forbids spaces in the host component. The W3C validator flags this to help you catch what is almost certainly a mistake.
- SEO impact: Search engine crawlers will treat the URL as invalid and will not follow or index it.
How to fix it
- Check for typos: The most common fix is to correct the domain to the actual, valid domain name you intended.
- Replace spaces with hyphens: If the intended domain genuinely has a word separator, the standard convention is to use hyphens (e.g.,
my-domain.com). - Remove spaces entirely: Sometimes spaces are accidentally introduced and simply need to be removed (e.g.,
mydomain.com). - Check the path vs. host: If the space belongs in a file path or query parameter rather than the domain, make sure it's in the correct part of the URL and properly percent-encoded there.
Examples
❌ Literal space in the domain
<a href="http://my domain.com/page">Visit site</a>
❌ Percent-encoded space in the domain
<a href="http://my%20domain.com/page">Visit site</a>
✅ Fixed: use a hyphen in the domain
<a href="http://my-domain.com/page">Visit site</a>
✅ Fixed: remove the space entirely
<a href="http://mydomain.com/page">Visit site</a>
✅ Spaces are fine in the path (percent-encoded)
Note that %20 is valid in the path portion of a URL — just not in the domain:
<a href="http://mydomain.com/my%20page">Visit page</a>
Common mistake: space before or after the domain
Sometimes the space is hard to spot because it's at the beginning or end of the URL, or between the scheme and domain:
<!-- ❌ Trailing space in domain -->
<a href="http://mydomain.com /page">Visit site</a>
<!-- ✅ Fixed -->
<a href="http://mydomain.com/page">Visit site</a>
If your URLs are generated dynamically (e.g., from a CMS or database), make sure to trim whitespace from the domain portion before constructing the full URL. A quick way to catch these issues during development is to validate your HTML regularly with the W3C Markup Validation Service.
The URL in this href has a slash or backslash where the parser did not expect one, usually too many slashes after the scheme or a backslash standing in for the // separator.
After a scheme like https: the URL syntax expects exactly two forward slashes before the host: https://example.com. Adding a third slash (https:///example.com) leaves an empty host, and writing the separator with backslashes (https:\\example.com) uses a character the URL grammar does not allow there. In both cases the validator reports an unexpected slash or backslash.
This often comes from string concatenation that joins a base URL already ending in / with a path that also starts with /, or from copying a path that used backslashes. Browsers may paper over some of these, but the link can still resolve to the wrong place or fail in non-browser clients.
Invalid example
<a href="https:///example.com/page">Visit the page</a>
Valid example
<a href="https://example.com/page">Visit the page</a>
Keep exactly two forward slashes after the scheme, and use forward slashes throughout the URL.
A URL in an href attribute contains a username, password, or both (e.g., http://user:pass@example.com), which the W3C validator rejects because embedded credentials in URLs are a security risk.
Browsers have largely deprecated support for credentials in URLs. When a URL like http://user:password@example.com/page appears in HTML, the credentials are visible in the page source and can be leaked through referrer headers, proxy logs, or browser history. The WHATWG URL Standard defines username and password as URL components, but the HTML specification forbids their use in href attributes. Most modern browsers will strip the credentials or show a warning prompt rather than silently authenticate.
Remove the credentials from the URL. If authentication is required, handle it server side (redirects, session tokens, or an authentication flow) rather than embedding secrets in markup.
HTML examples
Invalid: URL with embedded credentials
<a href="https://admin:s3cret@example.com/dashboard">Dashboard</a>
Valid: URL without credentials
<a href="https://example.com/dashboard">Dashboard</a>
In the structure of a URL, the @ symbol has a special meaning: it separates the userinfo component (username and password) from the host. A URL with credentials follows this pattern:
scheme://username:password@hostname/path
When the username or password itself contains an @ character — for example, an email address used as a username — the browser or URL parser may not be able to determine where the credentials end and the hostname begins. For instance, in http://user@name:pass@example.com, it's unclear whether the host is name or example.com.
The URL Standard (maintained by WHATWG) requires that any @ appearing within the userinfo component be percent-encoded as %40. Percent-encoding replaces the literal character with a % followed by its hexadecimal ASCII code (40 for @). This removes the ambiguity and ensures all parsers interpret the URL identically.
While modern browsers may attempt to handle ambiguous URLs, the behavior is not guaranteed to be consistent across all user agents, link checkers, or HTTP clients. Properly encoding these characters ensures reliable behavior everywhere and keeps your HTML valid.
Note: Including credentials directly in URLs is generally discouraged for security reasons, as they may be exposed in browser history, server logs, and referrer headers. Consider alternative authentication methods when possible.
Examples
❌ Incorrect: unencoded @ in the username
<a href="http://user@name:password@example.com/path">Login</a>
Here, the parser cannot reliably distinguish user@name as the username from the @ that separates credentials from the host.
✅ Correct: percent-encoded @ in the username
<a href="http://user%40name:password@example.com/path">Login</a>
The @ within the username is encoded as %40, leaving only one literal @ to serve as the delimiter before the hostname.
❌ Incorrect: unencoded @ in the password
<a href="http://admin:p@ss@example.com/dashboard">Dashboard</a>
✅ Correct: percent-encoded @ in the password
<a href="http://admin:p%40ss@example.com/dashboard">Dashboard</a>
❌ Incorrect: email address used as username without encoding
<a href="ftp://joe@example.org:secret@ftp.example.com/files">Files</a>
✅ Correct: email address with @ percent-encoded
<a href="ftp://joe%40example.org:secret@ftp.example.com/files">Files</a>
To fix this issue, identify every @ character that appears before the final @ in the authority section of the URL and replace it with %40. The last @ in the authority is the actual delimiter and must remain as a literal character.
The <area> element defines a clickable region within an <map> element, which is used with images to create image maps. When an <area> element includes an href attribute, the browser treats it as a hyperlink. The value of href must be a valid URL, and http:// alone fails validation because the URL specification requires a host after the :// separator. An empty host is not permitted.
This matters for several reasons. Browsers may handle malformed URLs unpredictably — some might ignore the link, others might attempt navigation to a nonsensical destination, and others might throw a network error. Screen readers and other assistive technologies rely on valid href values to announce links correctly and provide meaningful navigation to users. From a standards compliance perspective, the WHATWG URL Standard explicitly rejects URLs with empty hosts, and the W3C validator flags this as an error.
This issue commonly appears when placeholder URLs are left in during development, when CMS tools generate incomplete markup, or when a URL value is dynamically constructed but the host portion ends up empty.
How to fix it
- If the area should link somewhere, replace
http://with the full, intended URL including the host (e.g.,https://example.com/page). - If the area is a temporary placeholder, use
href="#"to create a valid no-op link, though be aware this will scroll the page to the top when clicked. - If the area shouldn't be interactive, remove the
hrefattribute entirely. Withouthref, the<area>element is not a hyperlink and won't be clickable.
Examples
Invalid: empty host in URL
The value http:// has no host, which triggers the validation error.
<img src="diagram.png" alt="Site map" usemap="#siteMap">
<map name="siteMap">
<area shape="rect" coords="30,23,183,191" href="http://" alt="Home page">
</map>
Fixed: complete URL with a valid host
Providing a full URL with a host resolves the error.
<img src="diagram.png" alt="Site map" usemap="#siteMap">
<map name="siteMap">
<area shape="rect" coords="30,23,183,191" href="https://example.com/" alt="Home page">
</map>
Fixed: placeholder link with #
If you need the area to remain clickable but don't have a destination yet, href="#" is a valid placeholder.
<img src="diagram.png" alt="Site map" usemap="#siteMap">
<map name="siteMap">
<area shape="rect" coords="30,23,183,191" href="#" alt="Home page">
</map>
Fixed: non-interactive area without href
If the area doesn't need to be a link, simply omit the href attribute.
<img src="diagram.png" alt="Site map" usemap="#siteMap">
<map name="siteMap">
<area shape="rect" coords="30,23,183,191" alt="Home page">
</map>
Spaces in the href attribute of a <link> element are not valid URL characters and must be encoded as %20.
URLs follow the syntax defined in RFC 3986, which does not allow literal space characters in any component of a URI. The <link> element points to external resources such as stylesheets, icons, and preloaded files, and its href must be a valid URL. A browser often corrects the space on its own, but the markup is still invalid, so the validator flags it.
To fix the issue, replace each space in the URL with %20, the percent-encoded form of the space character. If the resource genuinely lives at a path that contains spaces, the encoding is still required for the reference to be valid.
This often appears with files whose names contain spaces, like an icon exported as Capture 2026-06-23.webp, or with folder names that include spaces.
HTML examples
Invalid: space in href
<link rel="icon" href="https://example.com/files/Capture 2026-06-23.webp">
Valid: spaces encoded as %20
<link rel="icon" href="https://example.com/files/Capture%202026-06-23.webp">
If you control the file or directory names, renaming them to avoid spaces is a simpler long term fix. Use hyphens or underscores instead:
<link rel="icon" href="https://example.com/files/capture-2026-06-23.webp">
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">
URLs used in HTML attributes must follow the URL Living Standard, which defines a specific set of characters that are allowed in each part of a URL. The query component of a URL — everything after the ? — permits most printable ASCII characters, but certain characters are still considered illegal and must be percent-encoded. When the W3C validator encounters one of these forbidden characters in the href of a <link> element, it raises this error.
Common characters that trigger this issue include:
| Character | Percent-encoded |
|---|---|
| ` | ` (pipe) |
[ (left bracket) | %5B |
] (right bracket) | %5D |
{ (left brace) | %7B |
} (right brace) | %7D |
^ (caret) | %5E |
` (backtick) | %60 |
| (space) | %20 |
Why this matters
While many modern browsers are lenient and will silently fix malformed URLs, relying on this behavior is risky. Invalid URLs can cause problems in several ways:
- Inconsistent browser behavior: Not all user agents handle illegal characters the same way, which can lead to broken stylesheets or resources failing to load.
- Interoperability issues: Proxies, CDNs, and other intermediaries may reject or mangle URLs with illegal characters.
- Standards compliance: Valid HTML requires valid URLs in attributes. An illegal character in the
hrefmakes the entire document non-conforming. - Copy-paste and sharing reliability: Malformed URLs are more likely to break when shared across systems, emails, or documentation.
How to fix it
Identify the illegal characters in your URL's query string and replace each one with its percent-encoded equivalent. If you're generating URLs programmatically, use a proper URL encoding function (e.g., encodeURIComponent() in JavaScript, urlencode() in PHP, or urllib.parse.quote() in Python) to ensure all special characters are encoded correctly.
Examples
❌ Illegal pipe character in the query string
This is a common pattern seen with Google Fonts URLs that use | to separate font families:
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans|Roboto">
✅ Pipe character percent-encoded
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans%7CRoboto">
❌ Square brackets in the query string
Some APIs or frameworks use bracket notation in query parameters:
<link rel="stylesheet" href="https://example.com/styles?themes[]=dark&themes[]=compact">
✅ Square brackets percent-encoded
<link rel="stylesheet" href="https://example.com/styles?themes%5B%5D=dark&themes%5B%5D=compact">
❌ Space character in the query string
<link rel="stylesheet" href="https://example.com/css?file=my styles.css">
✅ Space character percent-encoded
<link rel="stylesheet" href="https://example.com/css?file=my%20styles.css">
Note that for Google Fonts specifically, the modern API (v2) uses a different URL format that avoids the pipe character altogether. Where possible, consider updating to the latest version of an API rather than just encoding the old URL.
According to the HTML specification, the <a> element can exist without an href attribute, but in that case it represents a placeholder where a link might otherwise have been placed. However, the validator flags this as an issue because an <a> element without href and without role is ambiguous — browsers won't treat it as a link (it won't be focusable or keyboard-accessible), and assistive technologies won't know how to present it to users.
This matters for several reasons:
- Accessibility: Without
href, the<a>element loses its implicitrole="link"and is no longer announced as a link by screen readers. It also won't appear in the tab order, making it invisible to keyboard users. - Semantics: If the element is styled and scripted to behave like a button or link but lacks the proper attributes, it creates a disconnect between what users see and what the browser understands.
- Standards compliance: The spec expects you to be explicit about the element's purpose when
hrefis absent.
The most common cause of this issue is using <a> elements as JavaScript-only click targets without providing an href, or using them as styled containers without any interactive purpose.
How to Fix It
There are several approaches depending on your intent:
- Add an
hrefattribute if the element should be a link. This is the most common and recommended fix. - Add a
roleattribute if you're deliberately using<a>withouthreffor a specific purpose, such asrole="button". - Use a different element entirely. If it's not a link, consider using a
<button>,<span>, or another semantically appropriate element.
Examples
❌ Missing both href and role
<a>Click here</a>
This triggers the validator error because the <a> has neither href nor role.
❌ JavaScript-only handler without href
<a onclick="doSomething()">Submit</a>
Even with an event handler, the element lacks href and role, so it fails validation and is inaccessible to keyboard users.
✅ Fix by adding an href
<a href="/about">About us</a>
Adding href makes it a proper hyperlink — focusable, keyboard-accessible, and recognized by screen readers.
✅ Fix by adding role for a non-link purpose
<a role="button" tabindex="0" onclick="doSomething()">Submit</a>
If you must use <a> without href as a button, add role="button" and tabindex="0" to ensure it's focusable and properly announced. However, consider using a real <button> instead.
✅ Better: use the right element
<button type="button" onclick="doSomething()">Submit</button>
If the element triggers an action rather than navigating somewhere, a <button> is the correct semantic choice. It's focusable by default, responds to keyboard events, and doesn't need extra attributes.
✅ Placeholder anchor (intentional non-link)
<a role="link" aria-disabled="true">Coming soon</a>
If you're intentionally showing a placeholder where a link will eventually appear, you can add a role and indicate its disabled state for assistive technologies. Alternatively, use a <span> with appropriate styling to avoid the issue altogether.
Validate at scale.
Ship accessible websites, faster.
Automated HTML & accessibility validation for large sites. Check thousands of pages against WCAG guidelines and W3C standards in minutes, not days.
Pro Trial
Full Pro access. Cancel anytime.
Start Pro Trial →Join teams across 40+ countries