Today I learned that browsers now have a built-in HTML Sanitizer API. I’ve shipped DOMPurify more times than I can count just to safely inject user content, so this is welcome news.
Browser support
Note: This is still experimental, so feature-detect before using:
if ('Sanitizer' in window) {
element.setHTML(content);
} else {
// Fall back to DOMPurify or other library
}Check MDN and caniuse for current support. As of late 2025, it’s available in Firefox 148 nightly only, and no other browsers, so you’ll be stuck with DOMPurify or another library for the short term!
The problem it solves
Using innerHTML with user-provided content lets arbitrary JavaScript run in your page. Any string that reaches innerHTML can contain <script> tags or event handlers that execute immediately. DOMPurify solves this, but it means shipping an extra dependency just to strip dangerous markup. Now browsers can handle it natively.
Basic usage
The simplest approach uses setHTML() on any element:
const untrustedString = 'Hello <script>alert("xss")</script> World!';
const element = document.getElementById('target');
element.setHTML(untrustedString);
console.log(element.innerHTML); // "Hello World!" - script removed!The browser automatically strips out dangerous elements like <script>, event handlers like onclick, and other XSS vectors.
Customizing what’s allowed
You can create a Sanitizer object to control exactly which elements and attributes are permitted:
// Only allow paragraphs and links with href
const sanitizer = new Sanitizer({
elements: ['p', 'a'],
attributes: ['href']
});
element.setHTML(userContent, { sanitizer });Or start with defaults and tweak:
const sanitizer = new Sanitizer();
sanitizer.removeElement('img'); // No images allowed
sanitizer.allowAttribute('class'); // But classes are fineWhen you need more danger
For trusted content that needs unsafe elements, there’s setHTMLUnsafe():
// Only use this with content you trust!
element.setHTMLUnsafe(trustedContent, { sanitizer });Parsing without inserting
You can also sanitize HTML without immediately inserting it:
const fragment = Document.parseHTML(untrustedHTML);
// Returns a sanitized DocumentFragment you can inspect or manipulateStill Firefox-only for now, but it’s the kind of API that makes you realize how much weight we’ve all been carrying around by default.