Guias HTML para codificação
Aprenda como identificar e corrigir erros comuns de validação HTML sinalizados pelo W3C Validator — para que as suas páginas cumpram os padrões e sejam renderizadas corretamente em todos os navegadores. Consulte também o nosso Guias de acessibilidade.
In URLs, certain characters must be percent-encoded — a process where a character is replaced by % followed by exactly two hexadecimal digits representing its byte value. For example, a space becomes %20, a hash becomes %23, and an ampersand becomes %26. The % character itself is the escape prefix, so when a URL parser encounters %, it expects the next two characters to be valid hexadecimal digits (0–9, A–F, a–f). If they aren’t, the URL is malformed.
This validation error typically arises in a few scenarios:
- A literal % is used in the URL without encoding. For instance, a filename or path segment contains a % sign that wasn’t converted to %25.
- An incomplete or corrupted percent-encoding sequence. Someone may have partially encoded a URL, leaving behind sequences like %G5 or %2 that don’t form valid two-digit hex codes.
- Copy-paste errors. A URL was pasted from a source that stripped characters or introduced stray % symbols.
This matters because browsers may interpret malformed URLs inconsistently. One browser might try to “fix” the URL by encoding the stray %, while another might pass it through as-is, leading to broken form submissions or unexpected server-side behavior. Ensuring valid URLs in the action attribute guarantees predictable behavior across all browsers and complies with both the WHATWG URL Standard and the HTML specification.
How to Fix
- Locate every % in the URL. Check whether each % is followed by exactly two hexadecimal digits (e.g., %20, %3A, %7E).
- Encode literal % characters. If a % is meant to appear as a literal character in the URL (not as part of a percent-encoding sequence), replace it with %25.
- Fix incomplete sequences. If a sequence like %2 or %GZ exists, determine the intended character and encode it correctly, or remove the stray %.
- Use proper encoding tools. In JavaScript, use encodeURIComponent() or encodeURI() to safely encode URLs. Most server-side languages have equivalent functions (e.g., urlencode() in PHP, urllib.parse.quote() in Python).
Examples
Literal % not encoded
This triggers the error because %d is not a valid percent-encoding sequence (d is only one character, and what follows may not be hex):
<!-- ❌ Bad: bare % not followed by two hex digits -->
<form action="/search?discount=20%off">
<button type="submit">Search</button>
</form>
Encode the % as %25:
<!-- ✅ Good: literal % encoded as %25 -->
<form action="/search?discount=20%25off">
<button type="submit">Search</button>
</form>
Incomplete percent-encoding sequence
Here, %2 is missing its second hex digit:
<!-- ❌ Bad: %2 is an incomplete sequence -->
<form action="/path/to%2file.html">
<button type="submit">Submit</button>
</form>
If the intent was to encode a / character (%2F), complete the sequence:
<!-- ✅ Good: complete percent-encoding for "/" -->
<form action="/path/to%2Ffile.html">
<button type="submit">Submit</button>
</form>
Invalid hex characters after %
The characters G and Z are not hexadecimal digits:
<!-- ❌ Bad: %GZ is not valid hex -->
<form action="/data%GZprocess">
<button type="submit">Go</button>
</form>
If %GZ was never intended as encoding, escape the % itself:
<!-- ✅ Good: literal % properly encoded -->
<form action="/data%25GZprocess">
<button type="submit">Go</button>
</form>
Using JavaScript to encode safely
When building URLs dynamically, use built-in encoding functions to avoid this issue entirely:
const query = "20% off";
const safeURL = "/search?q=" + encodeURIComponent(query);
// Result: "/search?q=20%25%20off"
This ensures every special character — including % — is properly percent-encoded before it’s placed in the action attribute.
URLs follow strict syntax rules defined by RFC 3986. Only a specific set of characters are allowed directly in a URL path segment — these include letters, digits, hyphens (-), periods (.), underscores (_), and tildes (~), along with a handful of sub-delimiters like !, $, &, ', (, ), *, +, ,, ;, and =. Any character outside this set — including spaces, angle brackets (< >), curly braces ({ }), pipe characters (|), backslashes (\), carets (^), and backticks (`) — must be percent-encoded.
Percent-encoding replaces the character with a % sign followed by its two-digit hexadecimal ASCII code. For example:
| Character | Percent-encoded |
|---|---|
| (space) | %20 |
| { | %7B |
| } | %7D |
| | | %7C | | < | %3C | | > | %3E | | ^ | %5E |
This validation error matters for several reasons. First, browsers may handle illegal characters inconsistently — some may silently encode them, while others may break the link or navigate to an unexpected destination. Second, tools that parse HTML (screen readers, search engine crawlers, link checkers) rely on well-formed URLs and may fail or behave unpredictably when they encounter illegal characters. Third, standards compliance ensures your HTML works reliably across all environments.
Common causes of this error include:
- Copying and pasting URLs from documents or emails that contain unencoded spaces or special characters.
- Template variables or placeholders left in href values (e.g., {{url}}).
- File paths with spaces used directly as URLs without encoding.
- Non-ASCII characters in URLs that haven’t been properly encoded.
Examples
❌ Space in the URL path
<a href="/my page/about us.html">About Us</a>
✅ Spaces percent-encoded as %20
<a href="/my%20page/about%20us.html">About Us</a>
❌ Curly braces from a template placeholder left in the markup
<a href="/products/{{product-id}}/details">View Details</a>
✅ Curly braces replaced with an actual value
<a href="/products/42/details">View Details</a>
❌ Pipe character in the path
<a href="/search/color|size">Filter Results</a>
✅ Pipe character percent-encoded as %7C
<a href="/search/color%7Csize">Filter Results</a>
❌ Angle brackets in the URL
<a href="/page/<section>">Go to Section</a>
✅ Angle brackets percent-encoded
<a href="/page/%3Csection%3E">Go to Section</a>
How to Fix
- Identify the illegal character from the validator’s error message — it typically tells you exactly which character is problematic.
- Replace it with the correct percent-encoded equivalent using the table above or a URL encoder tool.
- If the URL contains template syntax (like {{...}}), make sure your templating engine processes it before the HTML is served to the browser. The raw template syntax should never appear in the final rendered HTML.
- Consider renaming files and directories to avoid spaces and special characters altogether — this is the cleanest long-term solution.
If you’re generating URLs programmatically, use built-in encoding functions like JavaScript’s encodeURIComponent() or PHP’s rawurlencode() to ensure all special characters are properly escaped before inserting them into href attributes.
The W3C HTML Validator checks that URLs in href attributes conform to the URL standard (defined by WHATWG). While square brackets are permitted in the host component of a URL (to support IPv6 addresses like [::1]), they are not valid unescaped characters in the query string — the part of the URL that comes after the ?. When the validator encounters a literal [ or ] in the query portion, it flags it as an illegal character.
This issue commonly arises when working with APIs or server-side frameworks that use square brackets in query parameters to represent arrays or nested data structures. For example, PHP-style query strings like ?filter[name]=foo or ?ids[]=1&ids[]=2 contain brackets that must be encoded for valid HTML.
Why this matters
- Standards compliance: The WHATWG URL Standard explicitly lists square brackets among the characters that must be percent-encoded in query strings. Invalid URLs cause W3C validation failures.
- Browser behavior: While most modern browsers are forgiving and will often handle unescaped brackets correctly, relying on this lenient parsing is fragile. Some HTTP clients, proxies, or intermediary servers may reject or mangle URLs with illegal characters.
- Interoperability: Encoded URLs are safer when copied, shared, or processed by tools like link checkers, web scrapers, or email clients that may perform strict URL parsing.
How to fix it
Replace every literal square bracket in the query string with its percent-encoded form:
| Character | Percent-encoded |
|---|---|
| [ | %5B |
| ] | %5D |
If you’re generating URLs dynamically in a server-side language or JavaScript, use the appropriate encoding function (e.g., encodeURIComponent() in JavaScript, urlencode() in PHP, or urllib.parse.quote() in Python) to handle this automatically.
Examples
Incorrect: literal brackets in the query string
<a href="https://example.com/search?filter[status]=active">Active items</a>
This triggers the validation error because [ and ] appear unescaped in the query.
Correct: percent-encoded brackets
<a href="https://example.com/search?filter%5Bstatus%5D=active">Active items</a>
Replacing [ with %5B and ] with %5D resolves the error. The server receiving this request will decode the values back to filter[status]=active.
Incorrect: array-style parameters with brackets
<a href="/api/items?ids[]=1&ids[]=2&ids[]=3">Load items</a>
Correct: array-style parameters encoded
<a href="/api/items?ids%5B%5D=1&ids%5B%5D=2&ids%5B%5D=3">Load items</a>
Note that in addition to encoding the brackets, the & characters in HTML attributes should be written as & for fully valid markup.
Incorrect: brackets in a simple value
<a href="search.html?q=[value]">Search</a>
Correct: encoded brackets in a simple value
<a href="search.html?q=%5Bvalue%5D">Search</a>
Note on brackets in the host (valid use)
Square brackets are valid in the host portion of a URL for IPv6 addresses. The following does not trigger the error:
<a href="http://[::1]:8080/page">IPv6 localhost</a>
The validator only flags brackets that appear in the query string or other parts of the URL where they are not permitted.
The W3C HTML Validator raises this error when it encounters a backslash character (\) inside the href attribute of an anchor element. According to the WHATWG URL Standard, backslashes are not valid characters in URL scheme data. URLs are defined with forward slashes (/) as delimiters — this applies to all parts of a URL, including the scheme, authority, path, query, and fragment.
This issue most commonly occurs when developers copy file paths from Windows operating systems, where backslashes are the default path separator (e.g., C:\Users\Documents\file.html), and paste them directly into HTML markup. It can also happen when server-side code generates URLs using OS-level path functions that produce backslashes on Windows.
Why this matters
- Standards compliance: The WHATWG URL Standard explicitly forbids backslashes in scheme data. Validators flag this as an error because the resulting URL is malformed.
- Cross-browser inconsistency: While some browsers may silently correct backslashes to forward slashes, this behavior is not guaranteed across all browsers or versions. Relying on browser error correction leads to fragile code.
- Broken links: Certain browsers, HTTP clients, or intermediary servers may not auto-correct the backslash, causing the link to fail entirely — resulting in 404 errors or unexpected navigation.
- Security concerns: Backslashes in URLs can be exploited in certain attack vectors like open redirects or path traversal attacks. Using well-formed URLs reduces the attack surface.
How to fix it
- Replace all backslashes (\) with forward slashes (/) in your href values.
- Check for URL generation in server-side code. If your application builds URLs programmatically, ensure it uses forward slashes regardless of the host operating system.
- Use relative or absolute URLs consistently. Whether the URL is relative (images/photo.jpg) or absolute (https://example.com/images/photo.jpg), always use forward slashes.
Examples
Incorrect: backslashes in a relative path
<a href="pages\about\team.html">Meet the Team</a>
Correct: forward slashes in a relative path
<a href="pages/about/team.html">Meet the Team</a>
Incorrect: backslashes in an absolute URL
<a href="https://example.com\blog\2024\post.html">Read the Post</a>
Correct: forward slashes in an absolute URL
<a href="https://example.com/blog/2024/post.html">Read the Post</a>
Incorrect: Windows file path pasted directly
<a href="assets\downloads\report.pdf">Download Report</a>
Correct: converted to a proper relative URL
<a href="assets/downloads/report.pdf">Download Report</a>
Incorrect: mixed slashes
Sometimes a URL contains a mix of forward and backslashes, which also triggers this error:
<a href="https://example.com/images\photos\sunset.jpg">View Photo</a>
Correct: all forward slashes
<a href="https://example.com/images/photos/sunset.jpg">View Photo</a>
A quick way to audit your HTML files is to search for \ within any href (or src, action, etc.) attribute values and replace them with /. In most code editors, you can use find-and-replace scoped to attribute values to handle this efficiently.
URLs follow strict syntax rules defined by RFC 3986. Within the path segment of a URL, only a specific set of characters is allowed: unreserved characters (letters, digits, -, ., _, ~), percent-encoded characters (like %20), and certain reserved sub-delimiters. When the W3C validator encounters a character outside this allowed set in a <link> element’s href attribute, it flags the error.
Common causes of this issue include:
- Template placeholders left in the URL, such as {{variable}} or ${path}, where curly braces and dollar signs haven’t been resolved or encoded.
- Spaces in file paths, such as href="styles/my file.css" instead of using %20 or renaming the file.
- Copy-paste errors that introduce invisible or special Unicode characters.
- Backslashes (\) used instead of forward slashes (/), which is a common mistake on Windows systems.
- Unencoded query-like characters placed in the path portion of the URL.
This matters because browsers may interpret malformed URLs inconsistently. A URL that works in one browser might fail in another. Additionally, invalid URLs can break resource loading, cause accessibility issues when assistive technologies try to process the document, and lead to unexpected behavior with proxies, CDNs, or other intermediaries that strictly parse URLs.
To fix the issue, inspect the href value reported in the error and either:
- Remove the illegal character if it was included by mistake.
- Percent-encode the character if it must be part of the URL (e.g., a space becomes %20, a pipe | becomes %7C).
- Rename the referenced file or directory to avoid special characters altogether (the simplest and most reliable approach).
Examples
Incorrect: Space in the path
<link rel="stylesheet" href="styles/my styles.css">
The space character is not allowed in a URL path segment. The validator will flag this as an illegal character.
Fixed: Percent-encode the space
<link rel="stylesheet" href="styles/my%20styles.css">
Better fix: Rename the file to avoid spaces
<link rel="stylesheet" href="styles/my-styles.css">
Incorrect: Template placeholder left unresolved
<link rel="stylesheet" href="styles/{{theme}}/main.css">
Curly braces { and } are not valid in URL path segments. This commonly happens with server-side or client-side templating syntax that wasn’t processed before the HTML was served.
Fixed: Use a valid resolved path
<link rel="stylesheet" href="styles/dark/main.css">
Incorrect: Backslash used as path separator
<link rel="stylesheet" href="styles\main.css">
Backslashes are not valid URL characters. URLs always use forward slashes.
Fixed: Use forward slashes
<link rel="stylesheet" href="styles/main.css">
Incorrect: Pipe character in the URL
<link rel="stylesheet" href="styles/font|icon.css">
Fixed: Percent-encode the pipe character
<link rel="stylesheet" href="styles/font%7Cicon.css">
Full valid document example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My Webpage</title>
<link rel="stylesheet" href="styles/main.css">
<link rel="icon" href="images/favicon.ico">
</head>
<body>
<h1>Welcome to my webpage!</h1>
<p>Here is some content.</p>
</body>
</html>
When in doubt, run your URL through a URL encoder or validator separately to confirm all characters are legal. As a general best practice, stick to lowercase letters, digits, hyphens, and forward slashes in your file and directory names—this avoids encoding issues entirely and makes your URLs clean and predictable.
Square brackets ([ and ]) are reserved characters under RFC 3986, the standard that defines URI syntax. They are only permitted in the host component of a URL (specifically for IPv6 addresses) and are illegal elsewhere, including the query string. While most browsers are lenient and will load an <iframe> even when the src contains raw brackets, the W3C HTML Validator correctly flags this as an invalid URL value.
This pattern surfaces frequently when working with frameworks or APIs that use bracket notation to represent arrays or nested objects in query parameters — for example, filters[category]=news or items[0]=apple. These URLs work in a browser’s address bar because browsers silently fix malformed URLs, but the raw HTML itself is technically non-conforming.
Why it matters
- Standards compliance: A valid HTML document requires all attribute values that expect URLs to contain properly encoded URIs. Raw brackets violate this requirement.
- Interoperability: While mainstream browsers handle this gracefully, other HTML consumers — such as screen readers, web scrapers, embedded webview components, or email clients — may not be as forgiving.
- Maintainability: Properly encoded URLs are unambiguous and reduce the risk of subtle parsing bugs, especially when URLs are constructed dynamically or passed through multiple layers of processing.
How to fix it
There are two main approaches:
-
Percent-encode the brackets. Replace every [ with %5B and every ] with %5D in the URL. The server will decode them back to brackets automatically, so functionality is preserved.
-
Use alternative parameter naming. If you control the server, switch to a naming convention that avoids brackets altogether, such as dot notation (filters.category) or underscores (filters_category). This keeps the URL valid without any encoding.
If you’re generating the URL dynamically in JavaScript, you can use encodeURIComponent() on individual parameter keys and values, or use the URL and URLSearchParams APIs, which handle encoding automatically.
Examples
Incorrect — raw brackets in the query string
<iframe src="https://example.com/embed?filters[category]=news&filters[tags]=web"></iframe>
The [ and ] characters in the query string make this an invalid URL value, triggering the validator error.
Fixed — percent-encoded brackets
<iframe src="https://example.com/embed?filters%5Bcategory%5D=news&filters%5Btags%5D=web"></iframe>
Replacing [ with %5B and ] with %5D produces a valid URL. The server receives the same parameter names after decoding.
Fixed — alternative parameter naming
<iframe src="https://example.com/embed?filters.category=news&filters.tags=web"></iframe>
If the server supports it, using dot notation eliminates the need for brackets entirely, keeping the URL clean and valid.
Generating encoded URLs in JavaScript
<iframe id="content-frame"></iframe>
<script>
const url = new URL("https://example.com/embed");
url.searchParams.set("filters[category]", "news");
url.searchParams.set("filters[tags]", "web");
document.getElementById("content-frame").src = url.href;
// Result: https://example.com/embed?filters%5Bcategory%5D=news&filters%5Btags%5D=web
</script>
The URLSearchParams API automatically percent-encodes reserved characters, so you can write the parameter names naturally and let the browser produce a valid URL.
The URL specification (defined by WHATWG and RFC 3986) restricts which characters can appear unencoded in different parts of a URL. Square brackets are reserved characters that have a specific meaning in URLs — they are only permitted in the host portion (to wrap IPv6 addresses like [::1]). In the query string, they must be percent-encoded.
This issue commonly appears when frameworks (especially PHP, Ruby on Rails, or JavaScript libraries) generate URLs with array-style query parameters like ?filter[color]=red. While many browsers and servers are lenient and will interpret these URLs correctly, they are technically invalid according to the URL standard. The W3C validator enforces this rule strictly.
Beyond standards compliance, using unencoded square brackets can cause problems in practice. Some HTTP clients, proxies, or caching layers may reject or mangle URLs containing raw brackets. Percent-encoding these characters ensures your URLs are universally safe and interoperable across all systems.
How to fix it
You have two main approaches:
-
Percent-encode the brackets. Replace every [ with %5B and every ] with %5D in the URL. This preserves the parameter structure that your server or framework expects, while making the URL valid.
-
Restructure the query parameters. If your backend allows it, use flat parameter names with dot notation, underscores, or dashes instead of bracket syntax. For example, change size[width] to size_width or size.width.
If you’re generating URLs in JavaScript, the built-in encodeURI() function does not encode square brackets. Use encodeURIComponent() on individual parameter names or values, or manually replace [ and ] after constructing the URL.
Examples
❌ Invalid: unencoded square brackets in query string
<img src="/images/photo.jpg?size[width]=300&size[height]=200" alt="A sample photo">
The literal [ and ] characters in the query string trigger the validation error.
✅ Fixed: percent-encoded brackets
<img src="/images/photo.jpg?size%5Bwidth%5D=300&size%5Bheight%5D=200" alt="A sample photo">
Replacing [ with %5B and ] with %5D makes the URL valid. Most servers and frameworks will decode these automatically and interpret the parameters the same way.
✅ Fixed: flat parameter names without brackets
<img src="/images/photo.jpg?size_width=300&size_height=200" alt="A sample photo">
If you control the server-side logic, you can avoid brackets altogether by using a flat naming convention for your parameters.
❌ Invalid: brackets in more complex query strings
<img
src="/api/image?filters[type]=jpeg&filters[quality]=80&crop[x]=10&crop[y]=20"
alt="Processed image">
✅ Fixed: all brackets encoded
<img
src="/api/image?filters%5Btype%5D=jpeg&filters%5Bquality%5D=80&crop%5Bx%5D=10&crop%5By%5D=20"
alt="Processed image">
Encoding in JavaScript
If you build image URLs dynamically, handle the encoding in your code:
// Manual replacement approach
const url = "/images/photo.jpg?size[width]=300&size[height]=200";
const safeUrl = url.replace(/\[/g, "%5B").replace(/\]/g, "%5D");
img.src = safeUrl;
// Using URLSearchParams (automatically encodes brackets)
const params = new URLSearchParams();
params.set("size[width]", "300");
params.set("size[height]", "200");
img.src = `/images/photo.jpg?${params.toString()}`;
Both approaches produce a valid, properly encoded URL that will pass W3C validation.
The W3C HTML validator raises this error when the src attribute of an <img> element contains characters that are not permitted in a valid URI. The most common culprit is the < character, but other characters like >, {, }, |, \, ^, and backticks are also illegal in URIs according to RFC 3986.
This issue typically occurs in a few common scenarios:
- Template syntax left unresolved: Server-side or client-side template tags (e.g., <%= imageUrl %>, {{ image.src }}) appear literally in the HTML output instead of being processed into actual URLs.
- Copy-paste errors: HTML markup or angle brackets accidentally end up inside a src value.
- Malformed dynamic URLs: JavaScript or server-side code incorrectly constructs a URL that includes raw HTML or special characters.
This matters because browsers may fail to load the image or interpret the URL unpredictably. Invalid URIs can also cause issues with screen readers and assistive technologies that try to resolve the src to provide context about the image. Keeping your markup standards-compliant ensures consistent behavior across all browsers and environments.
How to fix it
- Check for unprocessed template tags. If you see template syntax like <%, {{, or similar in the rendered HTML, ensure your templating engine is running correctly and outputting the resolved URL.
- Use valid, well-formed URLs. The src value should be a properly formatted absolute or relative URL.
- Percent-encode special characters. If a special character is genuinely part of the URL (which is rare for <), encode it: < becomes %3C, > becomes %3E, and so on.
- Inspect your generated HTML. View the page source in your browser to confirm the actual output, rather than relying on what your code looks like before processing.
Examples
Incorrect — template syntax in src
The template tag was not processed, leaving a < character in the src attribute:
<img src="<%= user.avatar %>" alt="User avatar">
Incorrect — HTML accidentally inside src
Angle brackets from stray markup ended up in the URL:
<img src="images/<thumbnail>/photo.jpg" alt="Photo">
Correct — a valid relative URL
<img src="images/photo.jpg" alt="Photo">
Correct — a valid absolute URL
<img src="https://example.com/images/photo.jpg" alt="Photo">
Correct — special characters percent-encoded
If the URL genuinely requires characters that are not allowed in a URI, percent-encode them:
<img src="https://example.com/search?q=a%3Cb" alt="Search result">
In this case, %3C represents the < character in the query string, making the URI valid.
The srcset attribute on img and source elements accepts a comma-separated list of image candidate strings. Each candidate consists of a URL optionally followed by a width descriptor (e.g., 300w) or a pixel density descriptor (e.g., 2x). The URL in each candidate must conform to the URL Standard, which does not permit raw square brackets in the query string of an HTTP or HTTPS URL.
This issue commonly arises when a backend framework or CMS generates URLs that use square brackets in query parameters — for example, ?filter[size]=large or ?dimensions[]=300. While many browsers are lenient and will load these URLs anyway, they are technically invalid according to the URL specification. Using invalid URLs can lead to unpredictable behavior across different browsers, HTML parsers, and tools that process your markup. It also means your HTML fails W3C validation, which can mask other, more critical issues in your code.
You have two main approaches to fix this:
-
Percent-encode the brackets. Replace every [ with %5B and every ] with %5D. This preserves the intended query parameter structure while making the URL spec-compliant. Your server should interpret percent-encoded brackets identically to raw brackets.
-
Eliminate brackets from the URL. If you control the server-side code, consider using alternative query parameter conventions that don’t rely on brackets — for instance, using dot notation (filter.size=large), comma-separated values (dimensions=300,400), or repeated parameter names (dimension=300&dimension=400).
When fixing these URLs, also make sure each image candidate follows the correct format: a valid URL, followed by optional whitespace and a descriptor, with candidates separated by commas.
Examples
Incorrect — raw square brackets in query string
This triggers the validation error because [ and ] appear unescaped in the srcset URLs:
<img
src="photo.jpg"
srcset="photo.jpg?crop[width]=400 400w, photo.jpg?crop[width]=800 800w"
sizes="(max-width: 600px) 400px, 800px"
alt="A landscape photo">
Fixed — percent-encoded brackets
Replacing [ with %5B and ] with %5D makes the URLs valid:
<img
src="photo.jpg"
srcset="photo.jpg?crop%5Bwidth%5D=400 400w, photo.jpg?crop%5Bwidth%5D=800 800w"
sizes="(max-width: 600px) 400px, 800px"
alt="A landscape photo">
Fixed — brackets removed from URL design
If you can modify the server-side routing, restructuring the query parameters avoids the issue entirely:
<img
src="photo.jpg"
srcset="photo.jpg?crop_width=400 400w, photo.jpg?crop_width=800 800w"
sizes="(max-width: 600px) 400px, 800px"
alt="A landscape photo">
Incorrect — brackets with pixel density descriptors
The same problem occurs regardless of whether you use width descriptors or density descriptors:
<img
src="avatar.jpg"
srcset="avatar.jpg?size=[sm] 1x, avatar.jpg?size=[lg] 2x"
alt="User avatar">
Fixed — percent-encoded version
<img
src="avatar.jpg"
srcset="avatar.jpg?size=%5Bsm%5D 1x, avatar.jpg?size=%5Blg%5D 2x"
alt="User avatar">
Fixed — simplified query parameters
<img
src="avatar.jpg"
srcset="avatar.jpg?size=sm 1x, avatar.jpg?size=lg 2x"
alt="User avatar">
Namespace URIs in XML (and by extension in HTML) are identifiers, not actual URLs that a browser fetches. The W3C and WHATWG specifications define http://www.w3.org/1998/Math/MathML as the one and only valid namespace for MathML. Even though http:// and https:// point to the same server in practice, they are different strings — and namespace matching is purely a string comparison. Using https://www.w3.org/1998/Math/MathML creates what the spec considers an entirely different (and unrecognized) namespace.
This is a common mistake because modern best practices encourage using https:// for everything on the web. However, these namespace URIs were standardized long before HTTPS became the norm, and changing them would break backward compatibility across the entire XML ecosystem. The spec is explicit: only http://www.w3.org/1998/Math/MathML is permitted.
How to Fix It
You have two options depending on your document type:
-
HTML5 (recommended): Simply remove the xmlns attribute from the <math> element. The HTML5 parser recognizes <math> and automatically places it in the correct MathML namespace. No explicit declaration is needed.
-
XHTML or XML documents: If you’re serving your document as application/xhtml+xml or working in an XML context where explicit namespaces are required, use the exact URI http://www.w3.org/1998/Math/MathML with http://.
The same rule applies to other well-known namespaces like SVG (http://www.w3.org/2000/svg) and XHTML (http://www.w3.org/1999/xhtml) — always use the http:// form specified in the standard.
Examples
Invalid: using https:// in the namespace URI
The https:// scheme causes the validation error:
<math xmlns="https://www.w3.org/1998/Math/MathML">
<mi>x</mi><mo>+</mo><mn>1</mn>
</math>
Fixed: omit xmlns in HTML5
In an HTML5 document, the parser handles the namespace automatically, so the cleanest fix is to drop xmlns altogether:
<!DOCTYPE html>
<html lang="en">
<head>
<title>MathML Example</title>
</head>
<body>
<math>
<mi>x</mi><mo>+</mo><mn>1</mn>
</math>
</body>
</html>
Fixed: use the correct http:// URI
If you need to explicitly declare the namespace (for example, in XHTML served as XML), use the exact http:// URI:
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mi>x</mi><mo>+</mo><mn>1</mn>
</math>
Quick comparison
| Code | Valid? |
|---|---|
| <math xmlns="https://www.w3.org/1998/Math/MathML"> | ❌ Wrong scheme |
| <math xmlns="http://www.w3.org/1998/Math/MathML"> | ✅ Correct URI |
| <math> (in HTML5) | ✅ Namespace implied |
The accept attribute provides browsers with a hint about which file types the user should be able to select through the file picker dialog. While browsers may still allow users to select other file types, the attribute helps filter the file picker to show relevant files first, improving the user experience.
The W3C validator reports this error when it encounters tokens in the accept attribute that don’t conform to the expected format. The attribute value is parsed as a set of comma-separated tokens, and each token must be one of the following:
- A valid MIME type such as application/pdf, text/plain, or image/png (the / character separating type and subtype is required).
- A file extension starting with a period, such as .pdf, .docx, or .jpg.
- One of three wildcard MIME types: audio/*, video/*, or image/*.
Common mistakes that trigger this error include using bare file extensions without the leading dot (e.g., pdf instead of .pdf), using arbitrary words that aren’t valid MIME types, or including spaces in a way that creates malformed tokens. The HTML specification (WHATWG) defines strict rules for how these tokens are parsed, and violating them produces a validation error.
Getting this attribute right matters for several reasons. First, a correctly specified accept attribute helps users by pre-filtering the file picker, so they don’t have to hunt through unrelated files. Second, assistive technologies may use this attribute to communicate accepted file types to users. Third, some browsers may silently ignore a malformed accept value entirely, removing the helpful filtering behavior you intended.
To fix the issue, review each token in your accept attribute and ensure it matches one of the three valid formats listed above. If you’re unsure of the correct MIME type for a file format, consult the IANA Media Types registry. When in doubt, dot-prefixed file extensions (like .pdf or .docx) are often simpler and more readable.
Examples
Incorrect: bare words without dots or MIME type format
<input type="file" name="document" accept="doc, docx, pdf">
The tokens doc, docx, and pdf are neither valid MIME types (no /) nor valid file extensions (no leading .), so the validator rejects them.
Incorrect: spaces creating malformed tokens
<input type="file" name="photo" accept="image/png, image/jpeg">
While most browsers handle spaces after commas gracefully, the validator may flag this depending on parsing. It’s safest to avoid spaces or keep them minimal.
Correct: using dot-prefixed file extensions
<input type="file" name="document" accept=".doc,.docx,.pdf">
Correct: using valid MIME types
<input type="file" name="document" accept="application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/pdf">
Correct: mixing MIME types, extensions, and wildcards
<input type="file" name="media" accept="image/*,.pdf,video/mp4">
This accepts all image types, PDF files, and MP4 videos. Mixing formats is perfectly valid as long as each token individually conforms to the specification.
Correct: using wildcard MIME types for broad categories
<input type="file" name="photo" accept="image/*">
This allows the user to select any image file, regardless of specific format.
A URL fragment identifier is the part of a URL that follows the # symbol, typically used to link to a specific section within a page. The URL specification (RFC 3986 and the WHATWG URL Standard) defines a strict set of characters that are permitted in fragments. The > character (greater-than sign) is among those that are not allowed to appear literally. When the W3C HTML Validator encounters > inside an href value — whether in the fragment or elsewhere in the URL — it raises this error.
In most cases, the > character appears in a URL by accident — for example, from a copy-paste error, a typo where the closing > of the tag accidentally ends up inside the attribute value, or a malformed template expression. Less commonly, a developer may genuinely need the > character as part of the URL content.
Why This Matters
- Broken links: Browsers may interpret the > as the end of the HTML tag or handle the URL unpredictably, leading to broken navigation.
- Standards compliance: Invalid URLs violate both the HTML specification and URL syntax standards, causing validation failures.
- Accessibility: Screen readers and other assistive technologies rely on well-formed markup. A malformed href can confuse these tools and prevent users from reaching the intended destination.
- Interoperability: While some browsers may silently correct or ignore the invalid character, others may not. Valid URLs guarantee consistent behavior everywhere.
How to Fix It
- If the > is a typo or copy-paste error, simply remove it from the href value. This is the most common scenario.
- If the > is intentionally part of the fragment or URL, replace it with its percent-encoded equivalent: %3E.
- Review your templates or CMS output — this error often originates from template engines or content management systems that inject malformed values into href attributes.
Examples
Accidental > in the URL path
A common mistake is accidentally including the tag’s closing > inside the attribute value:
<!-- ❌ Invalid: ">" is not allowed in the URL -->
<a href="/page.php>">Read more</a>
Remove the stray >:
<!-- ✅ Valid: clean URL without illegal character -->
<a href="/page.php">Read more</a>
Illegal > in a fragment identifier
The > can also appear inside the fragment portion of the URL:
<!-- ❌ Invalid: ">" in the fragment -->
<a href="/docs#section->overview">Go to overview</a>
If the > is unintentional, remove it:
<!-- ✅ Valid: fragment without illegal character -->
<a href="/docs#section-overview">Go to overview</a>
If the > is genuinely needed in the fragment, percent-encode it:
<!-- ✅ Valid: ">" encoded as %3E -->
<a href="/docs#section-%3Eoverview">Go to overview</a>
Query string or path containing >
The same rule applies outside of fragments. If > appears anywhere in the URL, encode it:
<!-- ❌ Invalid: ">" in query parameter -->
<a href="/search?filter=price>100">Expensive items</a>
<!-- ✅ Valid: ">" percent-encoded as %3E -->
<a href="/search?filter=price%3E100">Expensive items</a>
Template output errors
If you are using a server-side template or JavaScript framework, ensure that dynamic values inserted into href are properly URL-encoded. For example, in a template that generates links:
<!-- ❌ Invalid: unencoded dynamic value -->
<a href="/results#filter=>50">View results</a>
<!-- ✅ Valid: properly encoded value -->
<a href="/results#filter=%3E50">View results</a>
Most server-side languages provide built-in URL encoding functions (e.g., encodeURIComponent() in JavaScript, urlencode() in PHP, urllib.parse.quote() in Python) that will handle this automatically. Always use these functions when inserting dynamic content into URLs.
A URL can have only one fragment identifier — the portion that comes after the single # symbol. When the browser encounters a # in a URL, it treats everything after it as the fragment. If a second # appears, it becomes an illegal character within that fragment because the fragment portion of a URL does not allow unencoded # characters. This violates the URL specification (WHATWG) and the HTML standard’s requirements for valid URLs in the href attribute.
This matters for several reasons:
- Standards compliance: Browsers may handle malformed URLs inconsistently, leading to unpredictable navigation behavior across different environments.
- Accessibility: Screen readers and assistive technologies rely on well-formed URLs to correctly announce link destinations and allow users to navigate.
- SEO and crawling: Search engine crawlers may fail to follow or index pages with invalid URLs.
The # character is perfectly valid when used exactly once to introduce a fragment. For example, #pricing or /faqs#pricing are fine. The issue arises when a second # appears, such as /faqs#guarantee#pricing, or when # is used in a part of the URL where it isn’t expected.
If you genuinely need a literal # character as part of a path or query string (not as a fragment delimiter), you must percent-encode it as %23.
Examples
❌ Invalid: Multiple # characters in the URL
This triggers the validator error because the fragment (guarantee#pricing) contains an illegal #:
<a href="/faqs#guarantee#pricing">Guarantee and Pricing</a>
✅ Fixed: Use a single fragment identifier
Link to one section at a time with a single #:
<a href="/faqs#guarantee">Guarantee</a>
<a href="/faqs#pricing">Pricing</a>
✅ Fixed: Encode the # if it’s meant as a literal character
If the # is part of the actual path or data (not a fragment delimiter), encode it as %23:
<a href="/faqs%23guarantee#pricing">Pricing</a>
In this case, /faqs%23guarantee is the path (containing a literal #), and pricing is the fragment.
Using fragments correctly in a table of contents
Fragments work well for in-page navigation. Each target element needs a matching id:
<nav>
<ul>
<li><a href="#pricing">Pricing</a></li>
<li><a href="#terms">Terms</a></li>
<li><a href="#guarantee">Guarantee</a></li>
</ul>
</nav>
<h2 id="pricing">Pricing</h2>
<p>All about pricing...</p>
<h2 id="terms">Terms</h2>
<p>You can find our terms at...</p>
<h2 id="guarantee">Guarantee</h2>
<p>We offer a guarantee...</p>
❌ Invalid: # in a query string or path without encoding
Sometimes this error appears when a URL accidentally includes an unencoded # in the wrong place:
<a href="/search?color=#ff0000">Red items</a>
✅ Fixed: Encode the # in the query value
<a href="/search?color=%23ff0000">Red items</a>
Here, %23ff0000 correctly represents the literal string #ff0000 as a query parameter value, rather than being misinterpreted as the start of a fragment.
Common causes
- Copy-pasting URLs from other sources that contain multiple # characters.
- Dynamically generated links where fragment values aren’t properly sanitized.
- Color codes in URLs like #ff0000 that need to be percent-encoded as %23ff0000.
- Concatenation errors in templates where a # is added both in the base URL and the appended fragment.
The fix is always the same: make sure your href contains at most one # used as the fragment delimiter, and percent-encode (%23) any # that is meant as a literal character.
The fragment portion of a URL (everything after the # symbol) follows the same encoding rules as the rest of the URL — literal space characters are not permitted. When a browser encounters a space in a URL fragment, it may try to correct it automatically, but this behavior is not guaranteed across all browsers and contexts. Relying on browser error-correction leads to fragile links that may break unpredictably.
This issue matters for several reasons. First, it produces invalid HTML that fails W3C validation. Second, fragment navigation (jumping to a specific section of a page) may not work correctly if the browser doesn’t auto-correct the space. Third, assistive technologies like screen readers rely on well-formed URLs to announce link destinations accurately. Finally, tools that parse or process HTML programmatically — such as crawlers, link checkers, and content management systems — may misinterpret or reject malformed URLs.
The most common scenario for this error is linking to an id attribute on the same page or another page where the id contains spaces. However, it’s worth noting that id values themselves cannot contain spaces in valid HTML (a space in an id would make it multiple invalid tokens). So if you’re writing both the link and the target, the best fix is often to correct the id itself by using hyphens or underscores instead of spaces.
How to Fix It
There are two main approaches:
- Percent-encode the spaces — Replace each space with %20 in the href value.
- Use space-free identifiers — Change the target id to use hyphens or camelCase, then update the fragment to match.
The second approach is strongly preferred because it fixes the root problem and produces cleaner, more readable markup.
Examples
❌ Invalid: Space in the fragment
<a href="https://example.com/page#some term">Go to section</a>
<a href="#my section">Jump to My Section</a>
✅ Fixed: Percent-encode the space
If you cannot control the target id (e.g., linking to an external page), percent-encode the space:
<a href="https://example.com/page#some%20term">Go to section</a>
✅ Better fix: Use a hyphenated id and matching fragment
When you control both the link and the target, use a space-free id:
<h2 id="my-section">My Section</h2>
<p>Some content here.</p>
<a href="#my-section">Jump to My Section</a>
❌ Invalid: Space in fragment linking to another page
<a href="/docs/getting-started#quick start guide">Quick Start Guide</a>
✅ Fixed: Matching hyphenated id
<!-- On the target page (/docs/getting-started): -->
<h2 id="quick-start-guide">Quick Start Guide</h2>
<!-- On the linking page: -->
<a href="/docs/getting-started#quick-start-guide">Quick Start Guide</a>
A note on id naming conventions
Since fragment identifiers reference id attributes, adopting a consistent id naming convention avoids this issue entirely. Common patterns include:
<!-- Hyphens (most common, used by many static site generators) -->
<section id="getting-started">
<!-- camelCase -->
<section id="gettingStarted">
<!-- Underscores -->
<section id="getting_started">
All three are valid and will never trigger a space-related validation error in your fragment links.
URLs follow strict syntax rules defined by RFC 3986, which does not permit literal space characters anywhere in a URI. When the W3C validator encounters a space in the href attribute of an <a> element — particularly within the query string (the part after the ?) — it flags it as an illegal character.
While most modern browsers will silently fix malformed URLs by encoding spaces for you, relying on this behavior is problematic for several reasons:
- Standards compliance: The HTML specification requires that href values contain valid URLs. A space makes the URL syntactically invalid.
- Interoperability: Not all user agents, crawlers, or HTTP clients handle malformed URLs the same way. Some may truncate the URL at the first space or reject it entirely.
- Accessibility: Screen readers and assistive technologies may struggle to interpret or announce links with invalid URLs.
- Link sharing and copy-pasting: If a user copies the link from the source or if the URL is used in an API or redirect, the unencoded space can cause breakage.
To fix this issue, replace every literal space character in the URL with %20. Within query string values, you can also use + as a space encoding (this is the application/x-www-form-urlencoded format commonly used in form submissions). If you’re generating URLs dynamically, use your programming language’s URL encoding function (e.g., encodeURIComponent() in JavaScript, urlencode() in PHP, or urllib.parse.quote() in Python).
Examples
Incorrect — spaces in the query string
<a href="https://example.com/search?query=hello world&lang=en">Search</a>
The space between hello and world is an illegal character in the URL.
Correct — space encoded as %20
<a href="https://example.com/search?query=hello%20world&lang=en">Search</a>
Correct — space encoded as + in query string
<a href="https://example.com/search?query=hello+world&lang=en">Search</a>
Using + to represent a space is valid within query strings and is commonly seen in URLs generated by HTML forms.
Incorrect — spaces in the path and query
<a href="https://example.com/my folder/page?name=John Doe">Profile</a>
Correct — all spaces properly encoded
<a href="https://example.com/my%20folder/page?name=John%20Doe">Profile</a>
Generating safe URLs in JavaScript
If you’re building URLs dynamically, use encodeURIComponent() for individual parameter values:
<script>
const query = "hello world";
const url = "https://example.com/search?query=" + encodeURIComponent(query);
// Result: "https://example.com/search?query=hello%20world"
</script>
Note that encodeURIComponent() encodes spaces as %20, which is safe for use in any part of a URL. Avoid using encodeURI() for query values, as it does not encode certain characters like & and = that may conflict with query string syntax.
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 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 %5B and %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 %5B and ] 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 %20 is 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.
A URL follows a specific structure defined by RFC 3986. The general format is:
scheme://host/path?query#fragment
The # character serves as the delimiter that introduces the fragment portion of the URL. It may only appear once in this role. Once the parser encounters the first #, everything after it is treated as the fragment identifier. A second # within that fragment is an illegal character because the fragment production in the URL specification does not permit unescaped # characters.
This validation error commonly arises from:
- Duplicate # characters — e.g., accidentally including two hash marks like /#?param=value#section.
- Misplaced query strings — putting ?key=value after the # instead of before it. While this may work in some single-page application routers, it results in the query being part of the fragment, and adding another # after that creates an invalid URL.
- Copy-paste errors — assembling URLs from multiple parts and inadvertently introducing an extra #.
This matters for several reasons. Browsers may handle malformed URLs inconsistently — some may silently truncate or ignore part of the URL, while others may fail to load the resource entirely. The W3C validator flags this because it violates the HTML specification’s requirement that the src attribute contain a valid URL. Invalid URLs can also cause issues with assistive technologies, link sharing, and automated tools that parse your HTML.
How to fix it
- Locate all # characters in the URL and determine which one is the intended fragment delimiter.
- Remove any duplicate # characters that were added by mistake.
- Move query parameters before the fragment — the ?query portion must come before the #fragment in a well-formed URL.
- Percent-encode if needed — if a literal # must appear as data within the fragment or query value (not as a delimiter), encode it as %23.
Examples
Incorrect: multiple # characters
The second # inside the fragment is illegal:
<iframe src="https://example.com/#?secret=123#abc"></iframe>
Correct: query before fragment
Move the query string before the # so the URL has a proper structure:
<iframe src="https://example.com/?secret=123#abc"></iframe>
Correct: single fragment, no query
If you only need a fragment identifier, use a single #:
<iframe src="https://example.com/#abc"></iframe>
Correct: percent-encoding a literal # in a value
If the fragment itself must contain a # as data (not as a delimiter), percent-encode it:
<iframe src="https://example.com/?secret=123#color=%23ff0000"></iframe>
Here, %23ff0000 represents the literal string #ff0000 within the fragment value, which is valid because the # is encoded.
Incorrect: hash-based routing with duplicate #
Some single-page app embed URLs use hash-based routing, which can lead to accidental double hashes:
<iframe src="https://app.example.com/#/dashboard#settings"></iframe>
Correct: use a single fragment for the route
Restructure the URL to use a single # with a combined path:
<iframe src="https://app.example.com/#/dashboard/settings"></iframe>
Or, if the application supports it, use standard path-based routing instead:
<iframe src="https://app.example.com/dashboard/settings"></iframe>
When the W3C HTML Validator reports “Bad value X for attribute src on element iframe: Illegal character in query: [ is not allowed”, it means your URL contains unencoded square brackets in the query portion (everything after the ?). While most modern browsers will silently handle these characters and load the resource anyway, the URL does not conform to the URI syntax defined in RFC 3986, which the HTML specification requires.
According to RFC 3986, square brackets are reserved characters that have a specific purpose: they are only permitted in the host component of a URI to denote IPv6 addresses (e.g., http://[::1]/). Anywhere else in the URI — including the query string — they must be percent-encoded. The HTML living standard (WHATWG) requires that URLs in attributes like src, href, and action be valid URLs, which means they must follow these encoding rules.
Why this matters
- Standards compliance: Invalid URLs cause W3C validation failures, which can indicate deeper issues in your markup.
- Interoperability: While mainstream browsers are forgiving, some HTTP clients, proxies, CDNs, or web application firewalls may reject or mangle URLs with unencoded square brackets.
- Consistent behavior: Percent-encoding reserved characters guarantees that the URL is interpreted the same way everywhere — in browsers, server logs, link checkers, and automated tools.
- Copy-paste reliability: When users or tools copy a URL from your HTML source, an already-encoded URL is less likely to break during transmission through email clients, messaging apps, or other systems.
How to fix it
Replace every occurrence of [ with %5B and ] with %5D within the query string of the URL. If you’re generating URLs server-side or in JavaScript, use the language’s built-in URL encoding functions rather than doing manual find-and-replace:
- JavaScript: encodeURIComponent() or the URL / URLSearchParams APIs
- PHP: urlencode() or http_build_query()
- Python: urllib.parse.urlencode() or urllib.parse.quote()
These functions will automatically encode square brackets and any other reserved characters.
Examples
❌ Invalid — unencoded square brackets in query string
<iframe src="https://example.com/embed?filter[status]=active&filter[type]=video"></iframe>
The validator flags [ and ] as illegal characters in the query component.
✅ Valid — square brackets percent-encoded
<iframe src="https://example.com/embed?filter%5Bstatus%5D=active&filter%5Btype%5D=video"></iframe>
Replacing [ with %5B and ] with %5D resolves the error. The server receives the exact same parameter values — most server-side frameworks (PHP, Rails, etc.) automatically decode percent-encoded characters before processing them.
❌ Invalid — square brackets in a timestamp parameter
<iframe src="https://example.com/report?time=[2024-01-01]"></iframe>
✅ Valid — timestamp parameter properly encoded
<iframe src="https://example.com/report?time=%5B2024-01-01%5D"></iframe>
Generating encoded URLs in JavaScript
If you’re setting the src dynamically, let the browser handle encoding for you:
<iframe id="report-frame"></iframe>
<script>
const url = new URL("https://example.com/embed");
url.searchParams.set("filter[status]", "active");
url.searchParams.set("filter[type]", "video");
document.getElementById("report-frame").src = url.toString();
</script>
The URLSearchParams API automatically percent-encodes the brackets, producing a valid URL in the src attribute.
A note on other elements
This same rule applies to any HTML attribute that accepts a URL — including href on <a> elements, action on <form> elements, and src on <script> or <img> elements. Whenever you place a URL in HTML, ensure all reserved characters in the query string are properly percent-encoded.
URLs follow strict syntax rules defined by RFC 3986. Within a URL’s path segment, only a specific set of characters is allowed to appear literally. When a character falls outside this allowed set, it must be percent-encoded — represented as a % sign followed by two hexadecimal digits corresponding to the character’s ASCII code. The W3C validator checks that every URL in your HTML conforms to these rules, and it flags any src value that contains raw illegal characters.
Characters that commonly trigger this error include:
| Character | Percent-encoded |
|---|---|
| (space) | %20 |
| [ | %5B |
| ] | %5D |
| { | %7B |
| } | %7D |
| | | %7C |
| ^ | %5E |
| ` | %60 |
Other reserved characters like ?, #, @, !, $, &, ', (, ), *, +, ,, ;, and = also need encoding when used as literal data in a path segment rather than as URL delimiters. The % character itself must be encoded as %25 if it appears literally.
Why This Is a Problem
- Browser inconsistency: While many modern browsers silently fix malformed URLs, not all do. Some browsers, older user agents, or HTTP clients may fail to load the resource or interpret the URL differently, leading to broken images.
- Standards compliance: Invalid URLs violate the HTML specification, which requires that attribute values containing URLs conform to valid URL syntax.
- Interoperability: Servers, CDNs, proxies, and caching layers may handle illegal characters unpredictably, causing intermittent failures that are difficult to debug.
- Accessibility: If a URL is malformed and the image fails to load, users relying on assistive technologies may not receive the intended content, even when appropriate alt text is provided.
How to Fix It
You have two main approaches:
- Percent-encode the illegal characters in the src value. Replace each offending character with its %XX equivalent.
- Rename the file to use only URL-safe characters. Stick to lowercase letters, digits, hyphens (-), underscores (_), and dots (.). This is the cleanest long-term solution.
If you’re generating URLs programmatically, use your language’s built-in URL encoding functions (e.g., encodeURIComponent() in JavaScript, urlencode() in PHP, or urllib.parse.quote() in Python).
Examples
Illegal characters in the filename
The square brackets in the src value are not allowed in a URL path segment:
<!-- ❌ Invalid: raw [ and ] in URL path -->
<img src="image[00].svg" alt="Company logo">
Fix by percent-encoding:
<!-- ✅ Valid: [ and ] are percent-encoded -->
<img src="image%5B00%5D.svg" alt="Company logo">
Fix by renaming the file:
<!-- ✅ Valid: filename uses only safe characters -->
<img src="image-00.svg" alt="Company logo">
Spaces in the filename
Spaces are one of the most common causes of this error:
<!-- ❌ Invalid: space in URL path -->
<img src="my photo.jpg" alt="Vacation photo">
<!-- ✅ Valid: space encoded as %20 -->
<img src="my%20photo.jpg" alt="Vacation photo">
<!-- ✅ Valid: filename uses a hyphen instead of a space -->
<img src="my-photo.jpg" alt="Vacation photo">
Curly braces in a template-like path
Sometimes filenames or paths contain curly braces from templating artifacts or naming conventions:
<!-- ❌ Invalid: raw { and } in URL path -->
<img src="icons/{home}.png" alt="Home icon">
<!-- ✅ Valid: curly braces percent-encoded -->
<img src="icons/%7Bhome%7D.png" alt="Home icon">
Best practice for file naming
The simplest way to avoid this error entirely is to adopt a consistent file naming convention that only uses URL-safe characters:
<!-- ✅ Valid: clean, URL-safe filenames -->
<img src="images/hero-banner-2024.webp" alt="Welcome banner">
<img src="photos/team_photo_01.jpg" alt="Our team">
URLs follow strict syntax rules defined by RFC 3986, which does not allow literal space characters in any part of a URL — whether in the path, query string, or fragment. While many browsers will silently handle spaces by encoding them before making a request, the raw HTML is still invalid. The W3C HTML validator flags this because the src attribute expects a valid URL, and a URL containing a raw space does not conform to the standard.
This issue commonly appears in two scenarios: spaces in file paths (e.g., my image.jpg) and spaces in query string values (e.g., ?search=my term). Both must be percent-encoded. The percent-encoded form of a space is %20. In query strings specifically, you may also see + used to represent spaces (as defined by application/x-www-form-urlencoded), which is also valid in that context.
Beyond standards compliance, raw spaces in URLs can cause real problems. Some older browsers or HTTP clients may truncate the URL at the first space, leading to broken images or failed resource loads. Spaces can also cause issues with link sharing, copy-pasting, and server-side URL parsing. Proper encoding ensures your URLs work reliably across all environments.
How to fix it
- Replace spaces with %20 in all parts of the URL. This is the universally safe approach.
- Rename files to avoid spaces altogether. Use hyphens (-) or underscores (_) instead of spaces in file and directory names.
- Use + in query strings if you prefer, though %20 works everywhere in a URL.
If you’re generating URLs programmatically, use built-in encoding functions like JavaScript’s encodeURI() or encodeURIComponent() to handle this automatically.
Examples
Spaces in the file path
This triggers the validation error because the file name contains a space:
<!-- ❌ Invalid: space in path segment -->
<img src="/images/my photo.jpg" alt="A vacation photo">
Fix it by encoding the space:
<!-- ✅ Valid: space encoded as %20 -->
<img src="/images/my%20photo.jpg" alt="A vacation photo">
Or better yet, rename the file to avoid spaces:
<!-- ✅ Valid: no spaces in file name -->
<img src="/images/my-photo.jpg" alt="A vacation photo">
Spaces in the query string
This triggers the error because the query parameter value contains a space:
<!-- ❌ Invalid: space in query string -->
<img src="https://example.com/image?title=sunset beach" alt="Sunset at the beach">
Fix by percent-encoding the space:
<!-- ✅ Valid: space encoded as %20 -->
<img src="https://example.com/image?title=sunset%20beach" alt="Sunset at the beach">
Using + is also acceptable in query strings:
<!-- ✅ Valid: space encoded as + in query string -->
<img src="https://example.com/image?title=sunset+beach" alt="Sunset at the beach">
Multiple spaces in a URL
When a URL has multiple spaces, each one must be encoded:
<!-- ❌ Invalid: multiple spaces -->
<img src="/uploads/user photos/trip to paris.jpg" alt="Trip to Paris">
<!-- ✅ Valid: all spaces encoded -->
<img src="/uploads/user%20photos/trip%20to%20paris.jpg" alt="Trip to Paris">
URLs follow strict syntax rules defined by RFC 3986, which does not allow literal space characters. When the W3C validator encounters a space in the src attribute of an <img> element, it reports it as an illegal character in the scheme data. While most modern browsers will attempt to handle spaces in URLs by automatically encoding them, relying on this behavior is not standards-compliant and can lead to broken images in certain contexts, such as when URLs are processed by other tools, APIs, or older browsers.
This issue commonly arises when file names contain spaces (e.g., my photo.jpg) and the path is copied directly into the HTML. It can also happen when a URL is incorrectly constructed by concatenating strings with unencoded values.
Beyond validation, unencoded spaces can cause real problems. A URL with a space may break when shared, copied, or passed through redirects. Email clients and messaging apps may truncate the URL at the space. Search engine crawlers might fail to index the resource correctly.
How to fix it
There are several ways to resolve this issue:
- Percent-encode spaces as %20 — Replace every literal space in the URL with %20.
- Rename the file — Remove spaces from file names entirely, using hyphens (-), underscores (_), or camelCase instead.
- Use proper URL encoding functions — If generating URLs dynamically (e.g., in JavaScript or a server-side language), use built-in encoding functions like encodeURI() or encodeURIComponent().
Renaming files to avoid spaces is generally the best long-term practice, as it prevents encoding issues across your entire workflow.
Examples
❌ Invalid: spaces in the src attribute
<img src="images/my photo.jpg" alt="A vacation photo">
<img src="/assets/blog posts/header image.png" alt="Blog header">
Both of these will trigger the validation error because the src value contains literal space characters.
✅ Fixed: spaces encoded as %20
<img src="images/my%20photo.jpg" alt="A vacation photo">
<img src="/assets/blog%20posts/header%20image.png" alt="Blog header">
✅ Fixed: file renamed to remove spaces
<img src="images/my-photo.jpg" alt="A vacation photo">
<img src="/assets/blog-posts/header-image.png" alt="Blog header">
A note on + vs %20
You may see spaces encoded as + in some contexts (e.g., query strings in form submissions using application/x-www-form-urlencoded). However, + is not a valid substitute for a space in a URL path. Always use %20 for spaces in the src attribute.
<!-- ❌ Incorrect: + does not represent a space in a URL path -->
<img src="images/my+photo.jpg" alt="A vacation photo">
<!-- ✅ Correct -->
<img src="images/my%20photo.jpg" alt="A vacation photo">
URLs follow strict syntax rules defined by RFC 3986, which does not permit literal space characters anywhere in the URI — including path segments, query strings, and fragment identifiers. When the W3C HTML Validator encounters a space in the src attribute of a <script> element, it flags it as an illegal character because the attribute value is not a valid URL.
While most modern browsers will silently fix this by encoding the space before making the request, relying on this behavior is problematic for several reasons:
- Standards compliance: The HTML specification requires that the src attribute contain a valid URL. A URL with a literal space is technically malformed.
- Cross-browser reliability: Not all user agents, proxies, or CDNs handle malformed URLs the same way. What works in one browser may fail in another context.
- Interoperability: Other tools that consume your HTML — such as linters, crawlers, screen readers, and build pipelines — may not be as forgiving as browsers.
- Copy-paste and linking issues: Literal spaces in URLs cause problems when users copy links or when URLs appear in plain-text contexts like emails, where the space may break the URL in two.
How to fix it
You have three options, listed from most recommended to least:
- Rename the file or directory to eliminate spaces entirely (e.g., use hyphens or underscores). This is the cleanest solution.
- Percent-encode the space as %20 in the src attribute value.
- Use a build tool or bundler that generates references with properly encoded or space-free paths automatically.
Avoid using + as a space replacement in path segments. The + character represents a space only in application/x-www-form-urlencoded query strings, not in URL path segments.
Examples
❌ Invalid: space in the path segment
<script src="https://example.com/media assets/app.js"></script>
The space between media and assets makes this an invalid URL.
✅ Fixed: percent-encode the space
<script src="https://example.com/media%20assets/app.js"></script>
Replacing the space with %20 produces a valid, standards-compliant URL.
✅ Better: rename to avoid spaces entirely
<script src="https://example.com/media-assets/app.js"></script>
Using a hyphen (or underscore) instead of a space is the preferred approach. It keeps URLs clean, readable, and free of encoding issues.
❌ Invalid: space in a local relative path
This issue isn’t limited to absolute URLs. Relative paths trigger the same error:
<script src="js/my script.js"></script>
✅ Fixed: encode or rename the local file
<script src="js/my%20script.js"></script>
Or, better yet:
<script src="js/my-script.js"></script>
Multiple spaces and other special characters
If a URL contains multiple spaces or other special characters, each one must be individually encoded. For example, { becomes %7B and } becomes %7D. A quick reference for common characters:
| Character | Encoded form |
|---|---|
| Space | %20 |
| [ | %5B |
| ] | %5D |
| { | %7B |
| } | %7D |
<!-- Invalid -->
<script src="libs/my library [v2].js"></script>
<!-- Valid -->
<script src="libs/my%20library%20%5Bv2%5D.js"></script>
<!-- Best: rename the file -->
<script src="libs/my-library-v2.js"></script>
Note that this same rule applies to the src attribute on other elements like <img>, <iframe>, <audio>, and <video>, as well as the href attribute on <a> and <link>. Whenever you reference a URL in HTML, make sure it contains no literal spaces.
When the browser’s HTML parser encounters a src attribute, it expects the value between the opening and closing quotes to be a valid URL. URLs have strict rules about which characters are permitted — a literal double quote (") is not one of them. If a " character appears inside the URL, the validator flags it as an illegal character in the query string (or other parts of the URL).
This error often doesn’t stem from an intentionally embedded quote in the URL itself. Instead, it’s usually a symptom of malformed HTML around the attribute. Common causes include:
- Stray quotes after the attribute value, such as writing src="https://example.com/script.js"async"" instead of properly separating attributes.
- Accidentally doubled closing quotes, like src="https://example.com/script.js"".
- Boolean attributes given empty-string values incorrectly, such as async"" instead of just async, which causes the parser to interpret the extra quotes as part of the preceding src value.
- Copy-paste errors that introduce smart quotes (" ") or extra quotation marks into the URL.
This matters for several reasons. Malformed src attributes can cause the script to fail to load entirely, breaking functionality on your page. It also violates the HTML specification, which can lead to unpredictable behavior across different browsers as each parser tries to recover from the error differently.
To fix the issue, carefully inspect the <script> tag and ensure that:
- The src attribute value contains only a valid URL with no unescaped " characters.
- The opening and closing quotes around the attribute value are properly balanced.
- Attributes are separated by whitespace — not jammed together.
- Boolean attributes like async and defer are written as bare keywords without values.
If you genuinely need a double quote character in a query string (which is rare), encode it as %22.
Examples
Incorrect — stray quotes between attributes
In this example, the async attribute is malformed as async"", which causes the parser to interpret the extra quotes as part of the src URL:
<script src="https://example.com/js/app.js?ver=3.1" async""></script>
Incorrect — doubled closing quote
Here, an extra " at the end of the src value creates an illegal character in the URL:
<script src="https://example.com/js/app.js?ver=3.1""></script>
Incorrect — smart quotes from copy-paste
Curly/smart quotes copied from a word processor are not valid HTML attribute delimiters and get treated as part of the URL:
<script src="https://example.com/js/app.js?ver=3.1"></script>
Correct — clean attributes with proper quoting
<script src="https://example.com/js/app.js?ver=3.1" async></script>
Correct — boolean attribute written as a bare keyword
Boolean attributes like async and defer don’t need a value. Simply include the attribute name:
<script src="https://example.com/js/app.js?ver=3.1" defer></script>
While async="async" is technically valid per the spec, the cleanest and most common form is the bare attribute. Avoid empty-string patterns like async="" placed without proper spacing, as they can lead to the exact quoting errors described here.
Correct — full valid document
<!DOCTYPE html>
<html lang="en">
<head>
<title>Valid Script Example</title>
<script src="https://example.com/js/app.js?ver=3.1" async></script>
</head>
<body>
<p>Page content here.</p>
</body>
</html>
If you’re generating <script> tags dynamically (through a CMS, template engine, or build tool), check the template source rather than just the rendered output. The stray quotes are often introduced by incorrect string concatenation or escaping logic in the server-side code.
Pronto para validar os seus sites?
Comece o seu teste gratuito hoje.