HTML Escaping vs Sanitizing: When to Use Each

You paste an HTML snippet into a page and get bold text where you wanted visible tags. Or you escape a rich-text description and its formatting disappears. Both problems start with the same decision: should the reader see the markup, or what the markup produces?

Browser support for sanitizing HTML took a useful step forward in 2026. Mozilla introduced the standardized Sanitizer API in Firefox 148 on February 24, and it appears in the Chrome 146 release notes for March 10. That gives developers a built-in option for inserting untrusted formatted content. Choosing the right operation still comes first.

Displaying text in a page

Suppose a tutorial needs to show this example literally:

<strong>Tea & biscuits</strong>

If JavaScript fills an existing <code id="example"> element, use textContent:

const example = document.getElementById("example");
example.textContent = "<strong>Tea & biscuits</strong>";

The reader sees the angle brackets and tag names. The browser does not turn the string into a bold element. textContent inserts a text node, so there is no need to encode the string first. Feeding it &lt;strong&gt; would display those entity spellings literally.

When you are writing the HTML source itself, escape the example instead:

<code>&lt;strong&gt;Tea &amp; biscuits&lt;/strong&gt;</code>

Our HTML encoder and decoder can prepare that inner text using its default HTML text (recommended) option. It is useful for a one-off documentation snippet. For application data, prefer your template engine’s automatic escaping; manually encoding text before an auto-escaping template can encode it twice.

Keeping formatting from untrusted HTML

A rich-text preview has a different requirement: readers should see emphasis and paragraphs, while dangerous content is removed. Escaping every tag would prevent the formatting too. This is where HTML sanitization belongs.

The browser’s setHTML() method parses, sanitizes, and inserts HTML into an element. It removes script elements and event-handler attributes, including when a custom configuration tries to allow them. The MDN reference documents its behavior and browser compatibility.

For an existing <div id="preview">, this example preserves simple formatting where the method is supported:

const preview = document.getElementById("preview");
const submittedHtml = '<p>Try <strong>tea</strong> &amp; biscuits.</p>';

if (typeof preview.setHTML === "function") {
  preview.setHTML(submittedHtml);
} else {
  preview.textContent = submittedHtml;
}

The fallback deliberately shows source text, including entity spellings. It sacrifices formatting without handing the string to innerHTML. Check support in your target browsers; if formatting is essential everywhere, use a maintained sanitizer with suitable compatibility. Keep sanitization at the insertion point: serializing sanitized content and inserting it elsewhere through innerHTML can reintroduce risk.

Decoding does not make HTML safe

Entity decoding converts &lt;strong&gt; back into <strong>. It does not assess whether the resulting markup is safe to render. Keep decoded text in a text field or text node unless you have deliberately chosen a sanitization step.

Likewise, HTML text escaping is not a universal escape function for URLs, JavaScript, CSS, or attribute values. Those contexts have their own rules. OWASP’s XSS prevention guidance explains context-specific encoding and when sanitization is appropriate.

Try the distinction in a layout

Generate a short HTML list with the Lorem Ipsum generator. Use it as formatting in your local mockup, then encode the same markup to show its source in a documentation example. You now have two useful presentations of the same content: a rendered list and the code that describes it.

Our post on using Lorem Ipsum HTML and lists has ideas for checking wrapping and spacing. Placeholder content helps with that visual check; it does not test whether your application handles untrusted HTML securely.

Premium is coming soon

An optional premium subscription to remove ads is planned. Subscriptions are not available yet.

You can keep using our free tools without an account.