HTML Guides for bad value
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 # 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 href of this link contains a curly brace, usually from template syntax like {{ ... }} that reached the HTML without being replaced by a real URL.
Curly braces aren't allowed in URLs. When a placeholder such as {{ menu.link }} or {id} ends up in the page, the browser gets the placeholder text instead of an address. A value like {{ menu.link }}, with no scheme or leading slash, is a relative URL, so the brace counts as part of the path. That's why the validator mentions a path segment. A stray } in the path gets the same message with } in place of {. A brace in the query string or the fragment is reported with a different message.
Client-side frameworks often cause this. In AngularJS, href="{{ menu.link }}" puts the raw expression in the HTML, and anything that reads the page before the script runs sees it: the validator, a crawler, or a visitor whose JavaScript failed to load. AngularJS has the ng-href directive for this case. Write it as data-ng-href so the attribute is valid HTML, and AngularJS sets href once the expression has a value. Until then the link has no href and can't be reached with the keyboard, so rendering the final URL on the server is the more reliable fix.
If the braces are meant to be literal characters in the URL, percent-encode them: { as %7B and } as %7D.
Invalid example
<a href="{{ menu.link }}">Products</a>
Valid example
The server renders the final URL:
<a href="/products/">Products</a>
Valid example with AngularJS
<a data-ng-href="{{ menu.link }}">Products</a>
The href value on the <a> element contains a literal > character, which is not allowed in a URL path.
The URL standard does not allow a raw > anywhere in a URL. Writing it as > doesn't change that, because the HTML parser decodes > back to > before the URL is read. Browsers still follow the link, but they percent-encode the character themselves and request a path that usually does not exist.
When the value starts with >, it is often not an address at all. Some sites put a > in front of link text as a small arrow, as in > Read the full report. If an editor pastes that text into the URL field of a CMS instead of the label field, the whole sentence becomes the href, and the browser treats it as a relative path to a missing page. A stray > at the end of a value, like href="/reports/annual>", is usually a typo in the markup.
Put the real address in href and keep the text inside the element. The validator reports only the first illegal character in a value, so if you remove the > but leave the sentence in href, it will report the spaces next. If a path really needs a >, write it as %3E.
Invalid example
<a href="> Read the full report">Read the full report</a>
Valid example
<a href="/reports/annual">Read the full report</a>
The href value on the <a> element contains a literal < character, which is not allowed in a URL path.
The URL standard does not allow a raw < anywhere in a URL. Escaping it as < does not help, because the HTML parser turns < back into < before the URL is read. If a path really needs the character, write it as %3C.
A value that starts with part of a tag, such as <div class=, means a template or content filter wrote HTML where a URL belongs. Lazy-loading and video embed plugins can do this when they swap a video URL for placeholder markup without checking whether the URL sits inside an attribute. The first " in that markup closes the href, so the value stops at class= and the browser treats it as a relative path to a page that doesn't exist.
The rest of the injected tag spills into the <a> start tag as broken attributes. That's why the validator usually also reports a stray end tag and a quote in an attribute name for the same link. Those errors go away once the href holds a plain URL.
Other values with a < come from angle brackets copied along with an address, as in <https://www.example.com/> from a plain-text email, or from placeholders like /files/<name>.pdf left in a template. Remove the brackets or fill in the real value.
Invalid example
<a href="<div class="video-embed" data-src="https://www.example.com/embed/abc123"></div>">Watch the video</a>
Valid example
<a href="https://www.example.com/embed/abc123">Watch the video</a>
The href value on the <a> element contains  (U+FFFC, the object replacement character), which isn't allowed in a URL path.
Rich-text editors and other text systems use U+FFFC as a placeholder for an inline image or other embedded object. Copying text out of one of them, or editing a link next to an inline image, can leave the placeholder inside the URL. Depending on the font, it's invisible or shows up as a small box, so the address can look right in the editor.
It never belongs in an address. Browsers send it as %EF%BF%BC, so /jobs/apply/ is requested as /jobs/apply%EF%BF%BC/, which most likely doesn't exist. Percent-encoding it yourself silences the validator but the link stays broken, so delete the character instead. Retyping the URL in the link field, or editing the link in the editor's HTML view, gets rid of it. To find every occurrence in a template or an export, run a regular-expression search for \uFFFC or \x{FFFC}, depending on the tool.
The same character in a query string or a fragment gets a similar message that names the query or the fragment instead of a path segment.
Invalid example
<a href="/jobs/apply/">Apply now</a>
Valid example
<a href="/jobs/apply/">Apply now</a>
The href value on the <a> element contains a literal | (pipe) character, which is not allowed in a URL path.
The URL standard doesn't list | among the characters a URL can contain, so a pipe in the path has to be written as %7C. Browsers still follow the link, but the markup is invalid.
This usually comes from a CMS or template that builds the path from a page title. A title like "Summer concert | Tickets" uses the pipe as a separator. If the slug function only lowercases the text and turns spaces into hyphens, the | stays and the path ends up as summer-concert-|-tickets. Fix the slug function so it drops anything other than letters, digits and hyphens. The new slug gives the page a new address, so redirect the old URL to it. If the URLs can't change, write the pipe as %7C in the href instead.
When the href is very long, the validator leaves the value out of the message. The cause and the fix are the same.
Invalid example
<a href="/events/42/summer-concert-|-tickets">Summer concert | Tickets</a>
Valid example
Remove the pipe from the slug:
<a href="/events/42/summer-concert-tickets">Summer concert | Tickets</a>
If the URL has to stay the same, percent-encode the pipe:
<a href="/events/42/summer-concert-%7C-tickets">Summer concert | Tickets</a>
The href value on the <a> element contains a literal " character, which is not allowed in a URL path.
The quotes around an attribute value are HTML syntax, not part of the URL. A " inside the value is different: written as ", or typed inside a single-quoted attribute such as href='"/brochure.pdf"', it becomes a character of the URL itself. The URL standard does not allow a raw " in a path, so the validator rejects the whole value. Browsers still follow the link, but they send the quote as %22 and request a path that usually does not exist.
The stray quote rarely comes from someone typing it. More often the code that writes the link adds it. A template that JSON-encodes the URL before printing it, for example with JSON.stringify(url), wraps the address in an extra pair of quotes. A CMS that stores link settings as JSON, like {"url":"/brochure.pdf","target":"_blank"}, can print the wrong piece of that string, so href ends up holding a fragment such as "url":"/brochure.pdf" or the tail of the object instead of the address. Fix the template so it outputs the plain URL. If a file name really contains a double quote, write it as %22 in the path.
Invalid example
<a href=""/brochure.pdf"">Download the brochure</a>
Valid example
<a href="/brochure.pdf">Download the brochure</a>
The href value on the <a> element contains � (U+FFFD, the Unicode replacement character), which the validator doesn't allow in a URL path.
A text decoder puts � in place of bytes that don't make a valid character in the encoding it's reading. In a URL, it marks where the original character, often a letter with an accent such as é, got lost. Browsers send it as %EF%BF%BD, so the link most likely leads to a page that doesn't exist.
Most of the time the page's encoding is to blame. With no <meta charset> in the document and no charset from the server, the validator falls back to windows-1252 and reads UTF-8 bytes as the wrong characters. The reverse mismatch is a page that declares utf-8 while the file is saved as windows-1252, where a byte such as 0xE9 (é) isn't valid UTF-8.
Either way, each byte that can't be decoded becomes �, and the report also shows "Malformed byte sequence" or "Unmappable byte sequence" errors. Leftover letters like à or  next to the � in the reported value point the same way. Save the file as UTF-8 and declare it with <meta charset="utf-8"> at the top of <head>, which also fixes any other garbled text on the page.
When the encoding is already right and the error doesn't go away, the � is in the source itself. The character was lost earlier, for example during an import into a CMS, and saved as �, so no encoding setting can bring it back. Write the intended character, percent-encode it (é is %C3%A9), or use an ASCII-only slug.
Invalid example
<a href="/menu/caf�-specials.html">Café specials</a>
Valid example
Save the file as UTF-8, declare the encoding and write the intended character:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Menu</title>
</head>
<body>
<a href="/menu/café-specials.html">Café specials</a>
</body>
</html>
To keep the URL ASCII-only, percent-encode the character instead:
<a href="/menu/caf%C3%A9-specials.html">Café specials</a>
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.
The URL in this link has a space in its port number, and a port can only contain digits.
In a URL such as https://example.com:8080/, the part after the colon that follows the host is the port. The URL Standard allows only digits there, up to the next /, ? or #. When the parser meets a space before that point, it gives up on the whole URL. A browser can't follow a link it can't parse, so clicking it does nothing.
The usual cause is a phone link written as http://tel: followed by a number with spaces between the digit groups, like http://tel:555 123 4567. The parser reads tel as a host name and the phone number as its port, then fails at the first space. Removing the spaces doesn't help. The link would point at a web server called tel, and most phone numbers are larger than 65535, the highest port allowed.
Phone links use the tel: scheme on its own, with no http:// in front, as defined in RFC 3966. A tel: URL can't contain spaces either, so write the digits together, starting with + and the country code. To keep the number easy to read, put the spaced version in the link text.
When the URL really has a port, the space is usually a typo or whitespace left by a template, as in https://example.com:8080 /reports. Delete it.
Invalid example
<p>Call us at <a href="http://tel:555 123 4567">555 123 4567</a>.</p>
<a href="https://example.com:8080 /reports">Open the reports</a>
Valid example
<p>Call us at <a href="tel:+15551234567">+1 555 123 4567</a>.</p>
<a href="https://example.com:8080/reports">Open the reports</a>
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
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 (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 URL in this link has a port number above 65535, the largest value a network port can have.
In a URL such as https://example.com:8080/, the digits after the colon that follows the host are the port. Ports are 16-bit numbers, so the URL Standard rejects any port greater than 65535. A browser can't parse a URL like that, and clicking the link does nothing.
The usual cause is a phone link written as http://tel: followed by the number. The URL parser reads tel as a host name and the phone number as its port, and almost every phone number is larger than 65535. Phone links use the tel: scheme on its own, with no http:// in front, as defined in RFC 3966.
A short number doesn't make http://tel: correct. http://tel:12345 passes validation because 12345 is a valid port, but the link points at a web server called tel instead of dialing. A number containing + or - gets a different error, Illegal character in port. Whatever the validator says, drop the http:// from phone links.
When the URL really is meant to carry a port, check the digits for a typo: valid ports go from 0 to 65535.
Invalid example
<a href="http://tel:5551234567">Call us</a>
<a href="https://example.com:80800/">Open the dashboard</a>
Valid example
<a href="tel:+15551234567">Call us</a>
<a href="https://example.com:8080/">Open the dashboard</a>
The URL in the href attribute has a tab or a line break inside it, and a valid URL can't contain either.
HTML lets the href value start or end with whitespace, so line breaks before or after the URL are allowed. Inside the URL they are not: the URL Standard counts every tab, line feed and carriage return as a validation error. Browsers remove these characters before they follow the link, so the first link in the invalid example below still opens https://example.com/courses/web-design/. Scripts that read the value with getAttribute("href") get the raw string with the line break in it, and a tool that doesn't strip the break the way browsers do may request the wrong address.
The line break often arrives with the content. A URL pasted into a CMS link field can carry one, and a template that splits a long URL across lines writes the break into the attribute. Some systems output it as a character reference: 
 or for a line feed, 	 for a tab.
The validator shows the decoded value, so the message contains a real line break even when the source has 
. Search the source for those references as well as for literal breaks, then fix the stored value or strip tabs and line breaks from the URL before the template writes it.
Invalid example
<a href="https://example.com/courses/web-design
/">Web design course</a>
<a href="https://example.com/courses/
web-design/">Web design course</a>
Valid example
<a href="https://example.com/courses/web-design/">Web design course</a>
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.
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 path in an <area> element's href can't contain a literal space, so write each space as %20 or take it out of the URL.
An <area> defines one clickable region of an image map. The <map> element groups the areas under a name, and an <img> points to that map with usemap="#name". An <area> with an href is a link, and the URL Standard doesn't allow spaces anywhere in a URL path. The usual cause is a page or file name with a space in it, like /islands/north island.
Browsers percent-encode the space before following the link, so the click usually still works. A crawler or a script that reads the raw value may not, and the markup is invalid either way.
Replace each space with %20. If you control the target URLs, hyphens (north-island) make cleaner addresses that need no encoding at all. A space after the ? triggers a different message, Illegal character in query, and %20 fixes that one too.
Every <area> with an href also needs an alt attribute. Screen readers announce it as the link text for that region, and the validator reports a missing one as a separate error.
Invalid example
<img src="islands.png" alt="Map of the islands" usemap="#islands" width="600" height="400">
<map name="islands">
<area shape="rect" coords="20,40,180,160" href="/islands/north island" alt="North Island">
<area shape="rect" coords="220,200,400,320" href="/islands/south island" alt="South Island">
</map>
Valid example: spaces encoded as %20
<img src="islands.png" alt="Map of the islands" usemap="#islands" width="600" height="400">
<map name="islands">
<area shape="rect" coords="20,40,180,160" href="/islands/north%20island" alt="North Island">
<area shape="rect" coords="220,200,400,320" href="/islands/south%20island" alt="South Island">
</map>
Valid example: hyphens instead of spaces
<img src="islands.png" alt="Map of the islands" usemap="#islands" width="600" height="400">
<map name="islands">
<area shape="rect" coords="20,40,180,160" href="/islands/north-island" alt="North Island">
<area shape="rect" coords="220,200,400,320" href="/islands/south-island" alt="South Island">
</map>
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">
Validate at scale.
Ship accessible websites, faster.
Automated HTML & accessibility validation for large sites. Check thousands of pages against WCAG guidelines and W3C standards in minutes, not days.
1K Weekly
1,000 monthly checks. Cancel anytime.
Get 1K Weekly →Join teams across 40+ countries