Element.setHTMLUnsafe() is an instance method that parses HTML into a DocumentFragment and replaces the element’s subtree. Unlike innerHTML, it parses declarative shadow roots. Learn MDN’s injection-sink warnings, TrustedHTML + Trusted Types, optional Sanitizer configs, when to prefer setHTML(), and five try-it labs aligned with MDN.
01
Kind
Instance method
02
Returns
undefined
03
Args
input, options
04
Default
No sanitizer
05
Shadow DOM
Declarative roots
06
Status
Baseline 2025
Fundamentals
Introduction
Sometimes you need to inject HTML from a string — CMS output, server-rendered fragments, or components with declarative shadow DOM. The familiar element.innerHTML = html approach does not parse declarative shadow roots and offers no built-in sanitization.
element.setHTMLUnsafe(input, options) parses the string into a DocumentFragment, optionally filters it with a Sanitizer, and replaces the element’s subtree (MDN). Declarative shadow roots in the input are parsed into real ShadowRoot nodes — something innerHTML cannot do.
⚠️
Injection sink (MDN)
The “Unsafe” suffix means no XSS filtering by default. Without a sanitizer, all HTML entities are injected — potentially less safe than innerHTML for script execution. MDN: almost always prefer setHTML() for user content.
input — TrustedHTML or HTML string to parse and inject (MDN).
options.sanitizer (optional) — Sanitizer, SanitizerConfig, or "default". If omitted, no sanitizer is used (MDN).
Return value
undefined (MDN).
Exceptions
TypeError — invalid SanitizerConfig, invalid string for sanitizer, or non-Sanitizer value (MDN).
Common patterns
JavaScript
const target = document.getElementById("target");
const html = '<p>Hello</p><script>alert(1)</script>';
// No sanitizer — all entities injected (MDN: injection sink!)
target.setHTMLUnsafe(html);
// Default XSS-safe sanitizer config (MDN)
target.setHTMLUnsafe(html, { sanitizer: "default" });
// TrustedHTML — no sanitizer needed when policy already sanitized
const trusted = policy.createHTML(html);
target.setHTMLUnsafe(trusted);
// Custom sanitizer — can allow script unlike setHTML() (MDN)
const sanitizer = new Sanitizer({ elements: ["div", "p", "script"] });
target.setHTMLUnsafe(html, { sanitizer });
Cheat Sheet
⚡ Quick Reference
Goal
Code
Inject trusted HTML
el.setHTMLUnsafe(trustedHtml)
XSS-safe filtering
el.setHTMLUnsafe(html, { sanitizer: "default" })
Custom sanitizer
el.setHTMLUnsafe(html, { sanitizer })
Declarative shadow DOM
el.setHTMLUnsafe(htmlWithShadowTemplate)
Feature detect
typeof el.setHTMLUnsafe === "function"
User content (MDN)
Prefer setHTML()
Snapshot
🔍 At a Glance
Four facts to remember about Element.setHTMLUnsafe().
Returns
undefined
No value
Default
no filter
Injection sink
Shadow DOM
parsed
vs innerHTML
Status
baseline
Sep 2025
Compare
📋 setHTMLUnsafe() vs other HTML APIs
setHTMLUnsafe()
setHTML()
innerHTML
Default sanitizes
No
Yes (always)
No
User input (MDN)
Avoid
Recommended
Dangerous
Declarative shadow roots
Yes (MDN)
Yes
No
Can allow script
With custom sanitizer
Never (MDN)
Yes
Returns
undefined
undefined
Assignment result
Best for
Trusted HTML, shadow DOM, edge cases
Untrusted HTML strings
Simple trusted markup
Hands-On
Examples Gallery
Examples follow MDN Element.setHTMLUnsafe() patterns. Use View Output or Try It Yourself for each case. Feature-detect setHTMLUnsafe and Sanitizer in supporting browsers.
📚 Getting Started
MDN’s injection sink demo—no sanitizer injects all HTML entities.
Example 1 — No sanitizer (MDN)
Parse and inject HTML without filtering. Use only with fully trusted strings.
JavaScript
const html = '<p>Hello</p><strong>Trusted markup</strong>';
const target = document.getElementById("target");
// No sanitizer — everything in the string is injected (MDN)
target.setHTMLUnsafe(html);
console.log(target.innerHTML);
MDN recommends TrustedHTML with a TrustedTypePolicy so sanitization is centralized. Enforce with the require-trusted-types-for CSP directive in production.
📈 Sanitizer Patterns
Default and custom Sanitizer configs with setHTMLUnsafe().
Example 3 — Default sanitizer "default" (MDN)
Apply the XSS-safe default sanitizer configuration when you cannot use setHTML().
MDN’s comparison: setHTML() removes all XSS-unsafe entities. setHTMLUnsafe() without a sanitizer keeps handlers like onclick. Use a sanitizer with allowAttribute("onclick") only when you have a controlled edge case.
Applications
🚀 Common Use Cases
Injecting HTML that contains declarative shadow roots (MDN).
Trusted server-rendered fragments where sanitization happened upstream.
Using TrustedHTML + Trusted Types at injection sinks (MDN).
Applying sanitizer: "default" when setHTML() is unavailable.
Edge cases requiring specific unsafe elements via a controlled Sanitizer.
Element.setHTMLUnsafe() is Baseline Newly available (MDN: across latest browsers since September 2025). Feature-detect on older engines. Logos use the shared browser-image-sprite.png sprite from this project.
✓ Baseline 2025
Element.setHTMLUnsafe()
Parse HTML with optional sanitization — supports declarative shadow roots.
BaselineNewly available 2025
Google ChromeSupported in current releases — feature-detect older
Yes
Microsoft EdgeSupported in current releases — feature-detect older
Yes
Mozilla FirefoxSupported in current releases — feature-detect older
Yes
Apple SafariSupported in current releases — feature-detect older
Yes
OperaFollow Chromium support
Yes
Internet ExplorerNot supported — use innerHTML or server sanitization
No
setHTMLUnsafe()Baseline
Bottom line: Detect typeof el.setHTMLUnsafe === "function". Prefer setHTML() for user content. Use TrustedHTML or sanitizer: "default" when you must call this API.
Wrap Up
Conclusion
Element.setHTMLUnsafe() parses HTML into the DOM with optional sanitization. MDN recommends setHTML() for almost all user content. Use setHTMLUnsafe() for declarative shadow DOM, TrustedHTML workflows, or controlled edge cases with a custom Sanitizer.
Five things to remember about Element.setHTMLUnsafe()
Parse HTML with optional filtering — use with care at injection sinks.
5
Core concepts
📝01
Returns
undefined
API
⚠️02
Default
no sanitizer
Sink
🌀03
Shadow DOM
declarative
Parse
🛡️04
TrustedHTML
preferred
Security
🌐05
Support
Baseline 2025
Sep 2025
❓ Frequently Asked Questions
It parses HTML input into a DocumentFragment, optionally sanitizes it, and replaces the element's subtree in the DOM (MDN). Unlike innerHTML, declarative shadow roots in the input are parsed.
No. MDN marks Element.setHTMLUnsafe() as Baseline 2025 (newly available since September 2025). It is not Deprecated, Experimental, or Non-standard.
undefined. There is no return value (MDN).
MDN: almost always. setHTML() always removes XSS-unsafe entities. Use setHTMLUnsafe() only for edge cases like declarative shadow roots or when you must allow specific unsafe HTML with a controlled sanitizer.
No by default. MDN warns it is an injection sink and potentially less safe than innerHTML when no sanitizer is used. Prefer TrustedHTML with Trusted Types, or setHTML() for user content.
Optional Sanitizer, SanitizerConfig, or "default" (XSS-safe default config). If omitted, no sanitizer runs and all HTML entities are injected (MDN).
Did you know?
MDN notes that setHTMLUnsafe() parses declarative shadow roots into real ShadowRoot nodes, while innerHTML does not. If your markup includes <template shadowrootmode="open">, this API is the right tool — but still sanitize untrusted input first.