HTML Guides for action
Learn how to identify and fix common HTML validation errors flagged by the W3C Validator — so your pages are standards-compliant and render correctly across every browser. Also check our Accessibility Guides.
The action attribute tells the browser where to send form data when the form is submitted. According to the WHATWG HTML living standard, if the action attribute is specified, its value must be a valid non-empty URL potentially surrounded by spaces. An empty string ("") does not satisfy this requirement, which is why the W3C validator flags it.
While some developers use action="" intending the form to submit to the current page’s URL, this approach is non-conforming HTML. Browsers do typically interpret an empty action as “submit to the current URL,” but relying on this behavior is unnecessary since simply omitting the action attribute achieves the same result in a standards-compliant way. When no action attribute is present, the form submits to the URL of the page containing the form — this is the defined default behavior per the HTML specification.
This issue matters for several reasons:
- Standards compliance: Non-conforming HTML can lead to unexpected behavior across different browsers or future browser versions.
- Maintainability: Using the correct approach makes your intent clearer to other developers. Omitting action explicitly signals “submit to the current page,” while action="" looks like a mistake or a placeholder that was never filled in.
- Tooling: Build tools, linters, and automated testing pipelines that rely on valid HTML may flag or break on this error.
How to Fix
You have two options:
- Remove the action attribute if you want the form to submit to the current page URL.
- Provide a valid URL if the form should submit to a specific endpoint.
Examples
❌ Invalid: Empty action attribute
<form action="" method="post">
<label for="email">Email:</label>
<input type="email" id="email" name="email">
<button type="submit">Subscribe</button>
</form>
This triggers the error: Bad value “” for attribute “action” on element “form”: Must be non-empty.
✅ Fixed: Remove the action attribute
If you want the form to submit to the current page, simply omit action:
<form method="post">
<label for="email">Email:</label>
<input type="email" id="email" name="email">
<button type="submit">Subscribe</button>
</form>
✅ Fixed: Provide a valid URL
If the form should submit to a specific endpoint, supply the URL:
<form action="/subscribe" method="post">
<label for="email">Email:</label>
<input type="email" id="email" name="email">
<button type="submit">Subscribe</button>
</form>
✅ Fixed: Use a hash as a placeholder for JavaScript-handled forms
If your form is entirely handled by JavaScript and should not navigate anywhere, you can use a # as the action or, preferably, omit action and prevent submission in your script:
<form method="post" id="js-form">
<label for="query">Search:</label>
<input type="text" id="query" name="query">
<button type="submit">Search</button>
</form>
document.getElementById('js-form').addEventListener('submit', function(e) {
e.preventDefault();
// Handle form data with JavaScript
});
In this case, omitting action is the cleanest solution. The JavaScript preventDefault() call stops the browser from actually submitting the form, so the action value is never used.
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.
Ready to validate your sites?
Start your free trial today.