HTML Tag Stripper
Strip HTML tags to get clean plain text, with options for decoding entities, preserving line breaks, and keeping link addresses rather than losing them.
The checkbox says "decode entities". It also swaps the parser.
With entity decoding on, this page hands your HTML to the browser's real parser, removes script
and style elements from the resulting tree, and reads the text out. With it off, it removes
tags with a regular expression: <[^>]*>.
Both are reasonable. The regex is predictable and leaves entities exactly as written, which is what you want if the "HTML" is a template you would rather keep intact. The parser is correct. The label only mentions entities, and entities turn out to be the smallest of the differences:
| Input | Regex path | Parser path |
|---|---|---|
Well-formed markup<p>Hello <b>world</b></p> | Hello world | Hello world |
Angle bracket in an attribute<div title="a>b">text</div> | b">text | text ← |
Unclosed script<p>before</p><script>alert(1) | before
alert(1) | before ← |
Comment containing an angle bracket<!-- a > b --><p>after</p> | b -->after | after ← |
Entities<p>AT&T <tag></p> | AT&T <tag> | AT&T <tag> ← |
Unclosed block tag<p>one<p>two | onetwo | one
two ← |
Attribute with a slash<a href="/x">link</a> | link | link |
Bare less-than in text<p>5 < 6 is true</p> | 5 < 6 is true | 5 < 6 is true |
Complete style block<style>p{color:red}</style><p>body</p> | body | body |
The two paths disagree on 5 of 9 samples, and only 1 of those disagreements is about entity decoding. The other 4 are about parsing.
Where the regex comes apart
An angle bracket inside an attribute. <[^>]*> stops at the first >, which in
<div title="a>b">text</div> sits inside the quoted value. So it deletes half the
tag and leaves b">text in your plain text where the parser gives
text.
An unclosed script. The script-removal pattern needs a closing tag, so
<p>before</p><script>alert(1) — truncated, as pasted HTML often is — loses the tag and
keeps the code as body text: before
alert(1). The parser treats everything
after the opening tag as script content and drops it. This is the one worth caring about:
plain text that contains code is exactly what the option was meant to prevent.
A comment containing an angle bracket. <!-- a > b --><p>after</p> ends, as far as the regex is concerned, at the
> in the middle, and the rest leaks out as
b -->after.
An unclosed block tag. <p>one<p>two has no closing
tags, so the line-break pass — which matches closers — finds nothing and the words run
together as onetwo. The parser closes the first paragraph
implicitly and the break appears. None of these are exotic; they are what real pasted HTML
looks like.
And where it is fine
Closed tags, attributes without angle brackets, a bare <p>5 < 6 is true</p> in
body text, a complete style block — the two paths agree exactly on
4 of the 9 samples. Most HTML is well-formed and most of the
time the regex is indistinguishable from the parser, which is precisely why the failure mode
is worth writing down: it does not show up until it does. The practical rule is to leave
entity decoding on unless you specifically need entities preserved, and if you turn it off,
read the output rather than trusting it.
How to use
- Paste HTML into the input.
- Choose whether to keep line breaks and link URLs.
- Decode entities if you want readable punctuation.
- Copy the plain text result.
Frequently asked questions
Why not just remove everything between angle brackets?
Because that breaks on perfectly ordinary content. A less-than sign in the text, a script block containing comparisons, or an attribute value containing a bracket will all confuse a naive pattern, and the result is either missing text or leftover markup. Proper parsing avoids this.
What happens to the line breaks?
By default, HTML collapses whitespace, so simply removing the tags produces one continuous paragraph. Preserving breaks means converting block-level elements — paragraphs, divs, list items, line breaks — into newlines before stripping, which is why that option exists separately.
Should I strip tags to prevent cross-site scripting?
No. Stripping is for producing readable text, not for security. Sanitising untrusted HTML properly means parsing it and allowing only a known-safe set of elements and attributes — a blocklist approach applied to markup has been defeated too many times to trust.
What happens to entities like &?
They remain as literal entity text unless you decode them, which usually looks wrong in plain text output. Decoding turns them back into the characters they represent, which is normally what you want — with the caveat that the result is then no longer safe to reinsert into HTML.
Can I keep the link addresses?
Yes, and it is often worth doing. Stripping tags naively discards every URL, leaving anchor text with no destination. The alternative is to append each address in brackets after its text, which keeps the information at the cost of some readability.
What about the content of script and style tags?
It should be removed entirely, not converted to text. Those elements contain code rather than prose, and a stripper that only removes the tags leaves a wall of JavaScript or CSS in the middle of your text — a common failure in quick implementations.
🔒 This tool runs entirely in your browser. Nothing you enter is uploaded, logged, or stored.