Skip to main content

DOMPurify

What is DOMPurify

DOMPurify is a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML, and SVG. It is written in JavaScript, MIT licensed, and available on npm as dompurify with TypeScript types bundled directly in the package (no separate @types install required). Currently at v3.x, it sees ~8M weekly npm downloads and has ~14k GitHub stars. DOMPurify runs in the browser using the native DOM parser, and can also run on Node.js via a jsdom or linkedom adapter. It is maintained by Cure53, a Berlin-based security research firm.

Why we recommend it

  • Prevents XSS from user-supplied HTML — whenever you render HTML from a rich-text editor, a markdown pipeline, or an external API, DOMPurify strips malicious scripts, event handlers, and dangerous elements before the content ever touches the DOM.
  • Battle-tested by security experts — Cure53 has a strong track record of responsible disclosure, ongoing audits, and rapid response to reported vulnerabilities.
  • Framework-agnostic — works alongside React, Vue, Astro, or plain JavaScript with no framework-specific adapter required.
  • Tiny and fast — ~7 kB minified + gzipped. Uses the browser's own HTML parser, so parsing is native-speed with no regex heuristics.
  • Simple API — a single call, DOMPurify.sanitize(dirtyHTML), returns a clean HTML string safe for innerHTML or React's dangerouslySetInnerHTML.
  • TypeScript-ready — types are bundled directly in the dompurify package; no separate @types install needed.
  • Configurable — allow-lists and deny-lists for tags and attributes let you tighten or relax the default rules to match your content policy.
  • Fits the Aliz stack — pairs directly with React's dangerouslySetInnerHTML pattern for safe rich-text rendering.

When to use

  • Rendering HTML from rich-text editors such as TipTap, Quill, or Draft.js
  • Displaying markdown-to-HTML output produced by libraries like marked or remark
  • Rendering HTML content sourced from external APIs, a CMS, or user submissions
  • Any use of dangerouslySetInnerHTML in React where the content is not fully developer-controlled

When NOT to use

  • Static, developer-controlled HTML — if there is no user input and no external content, sanitization adds overhead with no security benefit.
  • Plain-text content — React's default rendering and textContent already escape HTML. Sanitization is only needed when you are deliberately injecting raw HTML.
  • Primary server-side sanitization — DOMPurify is designed for the browser. On Node.js it requires a jsdom or linkedom adapter, which adds complexity and overhead. For sanitizing content before persisting it to a database, prefer a server-side library purpose-built for that environment.

Why over alternatives

  • vs sanitize-html — sanitize-html is Node.js-first and regex-based, making it slower and larger in the browser. DOMPurify uses the native DOM parser, is significantly faster, has a smaller footprint, and has a stronger security track record. Prefer sanitize-html only when you need server-side sanitization without a DOM environment.
  • vs xss (js-xss) — DOMPurify has broader, more consistent browser support, is maintained by dedicated security researchers, and offers a more thorough and configurable sanitization model.
  • vs manual sanitization — never roll your own HTML sanitizer. Custom regex or string-manipulation approaches are fragile and routinely bypassed by novel XSS payloads. Always use a dedicated, audited library.
dangerouslySetInnerHTML without sanitization is a common XSS vector

Passing unsanitized user content directly to dangerouslySetInnerHTML is one of the most frequent XSS mistakes in React applications. Always run the HTML through DOMPurify.sanitize() first:

import DOMPurify from 'dompurify';

function RichTextContent({ html }) {
return (
<div
dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(html) }}
/>
);
}

Resources