Format HTML online with readable indentation and line breaks. Paste compressed or messy markup and get back clean, consistently indented HTML you can copy into your project.
Formatted HTML will appear here
Paste HTML in the input panel and it formats automatically
Load sample data to get started
What this tool can do
Indent by Nesting
Two spaces per level, matching the XML Formatter
Attributes Preserved
IDs, classes, URLs and quoting stay as written
Void Elements Kept
img, br and input are never given a closing tag
Comments & Doctype Kept
HTML comments and the doctype pass through
Inline Text Intact
Text with inline tags stays on one line
Script & Style Untouched
Embedded JavaScript and CSS are copied verbatim
Copy & Download
Copy the formatted source or save it as .html
Fragments Welcome
Partial HTML formats without a full document
Methodology and approach
The formatter parses the markup and writes it back out with two-space indentation, keeping void elements, attributes, comments and embedded script or style content exactly as written - and leaving text mixed with inline tags on one line so its spacing never changes.
HTML that arrives from a minifier, a CMS export or a copied view-source is often written on one very long line, or indented by whichever editor last touched it. An HTML formatter rewrites that source with consistent indentation and line breaks so the nesting of the document is visible: which elements hold which, where a heading ends and a paragraph begins, and which attributes ride on which tag.
This tool reads the markup with an HTML-aware parser rather than a pattern that only inserts a line break between two angle brackets. It knows the difference between a void element and an element with content, between a tag and a less-than sign in plain text, and between markup and the JavaScript or CSS inside a script or style element - so the structure it prints is the structure the document actually has.
Paste the HTML into the input panel on the left. It is parsed and reformatted automatically as you type, and Ctrl+Enter forces a re-run at any time. The formatted markup appears in the output panel on the right, with a status line reporting how many elements were found and how many lines the result spans.
HTML parsers recover from markup that XML parsers reject, and so does this tool: a new list item closes the previous one, a block element closes an open paragraph, and elements still open at the end of the input are closed the way a browser closes them. The one thing it will report is a start or end tag that is never finished - an unclosed quote on an attribute, a tag with no ">" - because there is no way to guess what the rest of that tag was meant to be. When that happens your input is left untouched and the output panel says where the problem is.
When the result looks right, Copy puts the formatted source on the clipboard - the actual markup, indentation included - and Download saves it as a .html file. Everything runs in your browser; nothing is uploaded.
<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Example Page</title></head><body><main><h1>Hello World</h1><p>This is a sample paragraph.</p></main></body></html><!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Example Page</title>
</head>
<body>
<main>
<h1>Hello World</h1>
<p>This is a sample paragraph.</p>
</main>
</body>
</html>Every nesting level adds two spaces. Opening and closing tags line up with each other, an element with element children gets one child per line, and the indentation-only whitespace that was between those children in the source is replaced by the indentation this tool writes - so the same input always produces the same output.
Two situations deliberately keep their original layout. Text mixed with inline elements is written on one line, because a line break is whitespace and inserting one into "Hello <strong>world</strong>" would render a space that was not in the original. And the contents of pre, textarea, script and style elements are copied through exactly as written, because their whitespace - or their JavaScript and CSS - is not ours to rearrange.
Indentation is a readability aid, not a check: re-indented markup is not thereby validated, and the source of a page is not made faster by being easier to read.
<p>Hello <strong>world</strong>, welcome to <a href="/about">our website</a>.</p><p>Hello <strong>world</strong>, welcome to <a href="/about">our website</a>.</p>Yes. A doctype and a single root element are not required: a pasted snippet, several sibling elements and loose text between them are all formatted as they are written. Elements left open at the end of the fragment are closed implicitly, the same recovery a browser performs, so the output reads as a complete tree even when the input stopped in the middle.
A closing tag with nothing left open to close it - the stray </div> that survives a partial cut-and-paste - is passed through unchanged rather than dropped, so nothing you pasted disappears from the result.
Formatting is meant to change the source layout, not the document's content: the same elements, in the same order, with the same attributes and the same text. Browsers collapse the whitespace between elements when they render, so the indentation added around block-level markup does not change what a visitor sees.
The places where whitespace is not merely cosmetic are handled carefully. Text next to an inline element keeps its spacing, pre and textarea contents are copied byte for byte, and embedded JavaScript and CSS are never reformatted. If a stylesheet relies on white-space: pre in a place this tool indents, the printed source will differ from what you pasted in that spot - so a formatted document that must be byte-identical is worth diffing before you ship it.
Attributes are copied through in source order, with the quoting the document used: class="a b" keeps its double quotes, id='main' keeps its single quotes, an unquoted value such as type=checkbox stays unquoted, and a boolean attribute such as disabled or required keeps its bare form. IDs, classes, URL attributes and data attributes are never rewritten or reordered.
HTML comments, the <!DOCTYPE> declaration and processing instructions are copied out verbatim, and entity references such as and © pass through untouched - HTML defines named entities a document never declares, so - unlike the XML Formatter - no reference is checked against a declaration list.
Minified markup is the usual one: a whole page on a single line, from a build step or a view-source copy, where the structure is impossible to follow. Pasting it here expands it one element per line.
Inconsistent indentation is the second: hand-edited templates where some blocks use tabs and others use four spaces, so nothing lines up. The formatter re-indents everything to the same two-space grid.
The third is markup that is not finished. An attribute value with no closing quote or a start tag with no ">" is reported with the line and column it occurs on, your input is left exactly as it was, and the previous output is cleared so stale HTML is never shown next to text it does not belong to. Embedded JavaScript and CSS are a fourth: they are copied through exactly as written rather than reformatted, so any layout inside them belongs to your JavaScript or CSS formatter, not this one.
Reading minified HTML from view-source or a network response, when the structure of the page needs to be understood rather than guessed at. Reviewing a template or a CMS export before editing it, so the nesting is visible before a single change is made. Debugging a layout by confirming which element is really inside which. Preparing markup to share in a pull request or a support ticket, where unreadable source slows everyone down.
It is the wrong tool when the document needs to be checked against the HTML rules - that is validation, and the HTML Validator is the page for it - or when the goal is a smaller page, which is minification. For making HTML readable, this is the shortest path.
Common questions about this tool