HTML Validator

Paste HTML to find the tag that breaks the document structure. The checker parses markup the way the HTML spec does, so optional end tags are accepted and real mistakes are pinpointed.

Input

Settings

History

Load from URL

HTML is lenient, and that hides mistakes

Browsers almost never refuse HTML. A stray </span> is ignored, a missing > swallows the next tag into an attribute, and the page renders anyway, just not the way you intended. That is why structural errors in email templates, CMS snippets and server-rendered fragments go unnoticed until a layout breaks.

This page parses your markup with the same HTML parser Prettier uses and reports what a careful reader would flag:

  • A closing tag with nothing to close, such as </span> when the open element is a <p>, or a </div> after </html>. Usually an element was closed too early or a tag name was mistyped.
  • An opening tag that is never terminated, as in <button class="cta"<span>, where a missing > merges two tags.
  • End tags on void elements: <img>, <br>, <input> and <meta> cannot have a closing tag, so </img> is an error.
  • Unclosed attribute quotes or comments, reported as an unexpected end of input at the point where the parser ran out of text.

What is deliberately allowed

HTML has optional end tags, and the checker follows the spec rather than XHTML habits. <li>, <p>, <td>, <tr> and <option> close automatically when the next sibling starts, so <ul><li>One<li>Two</ul> is valid. Custom elements such as <order-summary> and boolean attributes without values are fine. Uppercase tag names are fine too. If you paste a fragment rather than a full document, it is validated as a fragment; no <!DOCTYPE> or <html> wrapper is required.

Reading the report

The line and column of the first problem are highlighted in the input, and the message comes from the parser, for example Unexpected closing tag "span" followed by a note about implied end tags. Count backwards from the reported position to find the element that was closed early. Until the markup parses again, the formatted HTML from your last good edit stays visible, faded, in the output pane. Once it parses, switch to the Preview tab to see the rendered result, which is sanitised before display.

Keyboard users can format with Ctrl/Cmd+Enter and copy the result with Ctrl/Cmd+Shift+C. All parsing is local to your browser.

Not a W3C conformance checker

Structural parsing is only part of HTML validity. This tool does not check content models (a <button> nested inside another <button>, a <li> outside a list), duplicate id values, duplicate attributes, missing alt text, deprecated elements or ARIA rules. An <a> that is never closed is also accepted, because the parser closes it at the end of its parent. For full conformance, run the page through the W3C Nu HTML Checker; for accessibility, use an audit tool such as axe or Lighthouse.

Examples

Closing the wrong element

Invalid: </span> closes nothing, because the open element is <strong>; the error points at the stray tag.

Input
<section class="orders">
  <h2>Orders</h2>
  <p>3 orders are <strong>pending</span></p>
</section>
Result
Line 3, column 34: Unexpected closing tag "span". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags
Open this example in the tool

Missing > merges two tags

Invalid: the opening <button> tag is never terminated, so the parser cannot tell where its attributes end.

Input
<button class="cta" onclick="checkout()"<span>Buy now</span></button>
Result
Line 1, column 1: Opening tag "button" not terminated.
Open this example in the tool

Closing tag on a void element

Invalid: <img> is a void element and cannot have an end tag.

Input
<figure>
  <img src="/img/keyboard.jpg" alt="Mechanical keyboard"></img>
  <figcaption>KB-104</figcaption>
</figure>
Result
Line 2, column 58: Void elements do not have end tags "img"
Open this example in the tool

Optional end tags are valid

Passes: <td>, <tr> and <p> close themselves when the next one starts, exactly as the HTML spec allows.

Input
<table>
  <tr><td>KB-104<td>Keyboard<td>129.90
  <tr><td>MS-220<td>Mouse<td>39.50
</table>
<p>Prices include GST
<p>Free delivery over 100 SGD
Output
<table>
  <tr>
    <td>KB-104</td>
    <td>Keyboard</td>
    <td>
      129.90
      <tr>
        <td>MS-220</td>
        <td>Mouse</td>
        <td>39.50</td>
      </tr>
    </td>
  </tr>
</table>
<p>Prices include GST</p>
<p>Free delivery over 100 SGD</p>
Open this example in the tool

Common errors and how to fix them

ErrorCauseFix
Unexpected closing tag "span". It may happen when the tag has already been closed by another tag.
Explained
An end tag does not match the element that is currently open, often after a typo or a copy that cut off part of a fragment.Find the matching opening tag and correct the name, or delete the stray end tag.
Opening tag "button" not terminated.A tag is missing its closing >, usually right before another tag starts.Add > after the last attribute.
Void elements do not have end tags "img"A closing tag was written for img, br, input, meta, link or another void element.Delete the end tag; void elements stand alone, optionally written as <img … />.
Unexpected character "EOF"The input ended inside an attribute value or comment, typically a missing closing quote or -->.Close the attribute quote or the comment near the reported position.

Frequently asked questions

Does this replace the W3C HTML validator?

No. It checks that the markup parses into a sensible tree: matching tags, terminated tags and attributes. The W3C Nu checker also enforces content models, attribute rules and deprecated features.

Why is a missing </p> or </li> not an error?

Because HTML defines those end tags as optional. The parser closes the element automatically when a sibling starts or the parent ends.

Can I validate Vue or Angular templates here?

Use the dedicated Vue and Angular formatters instead. Their template syntax, such as @click or @if blocks, is parsed correctly there.

Does it check inline CSS and JavaScript?

Embedded <style> and <script> content is formatted along with the markup. To check either one on its own, paste it into the CSS or JavaScript validator.

Related tools