Nectar of the Programming Masses
Miss any of our Open RFC calls?Watch the recordings here! »


0.14.0 • Public • Published



NPM version Build Status Coverage Status Dependency status NPM downloads Financial Contributors on Open Collective

HTML to React parser that works on both the server (Node.js) and the client (browser):

HTMLReactParser(string[, options])

It converts an HTML string to one or more React elements. There's also an option to replace an element with your own.


var parse = require('html-react-parser');
parse('<div>text</div>'); // equivalent to `React.createElement('div', {}, 'text')`

CodeSandbox | JSFiddle | | Examples



$ npm install html-react-parser --save


$ yarn add html-react-parser


<!-- HTMLReactParser depends on React -->
<script src=""></script>
<script src=""></script>
  window.HTMLReactParser(/* string */);


Import the module:

// ES Modules
import parse from 'html-react-parser';
// CommonJS
const parse = require('html-react-parser');

Parse single element:


Parse multiple elements:

parse('<li>Item 1</li><li>Item 2</li>');

Since adjacent elements are parsed as an array, make sure to render them under a parent node:

    <li>Item 1</li>
    <li>Item 2</li>

Parse nested elements:

parse('<body><p>Lorem ipsum</p></body>');

Parse element with attributes:

  '<hr id="foo" class="bar" data-attr="baz" custom="qux" style="top:42px;">'



The replace callback allows you to swap an element with another React element.

The first argument is an object with the same output as htmlparser2's domhandler:

parse('<br>', {
  replace: function (domNode) {
    console.dir(domNode, { depth: null });

Console output:

{ type: 'tag',
  name: 'br',
  attribs: {},
  children: [],
  next: null,
  prev: null,
  parent: null }

The element is replaced only if a valid React element is returned:

parse('<p id="replace">text</p>', {
  replace: domNode => {
    if (domNode.attribs && === 'replace') {
      return React.createElement('span', {}, 'replaced');

Here's an example that modifies an element but keeps the children:

import React from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import parse, { domToReact } from 'html-react-parser';
const html = `
  <p id="main">
    <span class="prettify">
      keep me and make me pretty!
const options = {
  replace: ({ attribs, children }) => {
    if (!attribs) return;
    if ( === 'main') {
      return <h1 style={{ fontSize: 42 }}>{domToReact(children, options)}</h1>;
    if (attribs.class === 'prettify') {
      return (
        <span style={{ color: 'hotpink' }}>
          {domToReact(children, options)}
console.log(renderToStaticMarkup(parse(html, options)));

Use the exported attributesToProps method to convert DOM attributes to React Props:

import React from 'react';
import parse, { attributesToProps } from 'html-react-parser';
const html = `
  <hr class="prettify" style="background:#fff;text-align:center" />
const options = {
  replace: node => {
    if (node.attribs && === 'hr') {
      const props = attributesToProps(node.attribs);
      return <hr {...props} />;


<h1 style="font-size:42px">
  <span style="color:hotpink"> keep me and make me pretty! </span>

Here's an example that excludes an element:

parse('<p><br id="remove"></p>', {
  replace: ({ attribs }) => attribs && === 'remove' && <Fragment />


The library option allows you to specify which component library is used to create elements. React is used by default if this option is not specified.

Here's an example showing how to use Preact:

parse('<br>', {
  library: require('preact')

Or, using a custom library:

parse('<br>', {
  library: {
    cloneElement: () => {
      /* ... */
    createElement: () => {
      /* ... */
    isValidElement: () => {
      /* ... */


This library passes the following options to htmlparser2 on the server-side:

  decodeEntities: true,
  lowerCaseAttributeNames: false

By passing your own options, the default library options will be replaced (not merged).

As a result, to enable decodeEntities and xmlMode, you need to do the following:

parse('<p /><p />', {
  htmlparser2: {
    decodeEntities: true,
    xmlMode: true

See htmlparser2 options.

Warning: By overriding htmlparser2 options, there's a chance of breaking universal rendering. Do this at your own risk.


Normally, whitespace is preserved:

parse('<br>\n'); // [React.createElement('br'), '\n']

By enabling the trim option, whitespace text nodes will be skipped:

parse('<br>\n', { trim: true }); // React.createElement('br')

This addresses the warning:

Warning: validateDOMNesting(...): Whitespace text nodes cannot appear as a child of <table>. Make sure you don't have any extra whitespace between tags on each line of your source code.

However, this option may strip out intentional whitespace:

parse('<p> </p>', { trim: true }); // React.createElement('p')


Is this library XSS safe?

No, this library is not XSS (cross-site scripting) safe. See #94.

Does this library sanitize invalid HTML?

No, this library does not perform HTML sanitization. See #124, #125, and #141.

Are <script> tags parsed?

Although <script> tags and their contents are rendered on the server-side, they're not evaluated on the client-side. See #98.

Why aren't my HTML attributes getting called?

This is because inline event handlers like onclick are parsed as a string instead of a function. See #73.

The parser throws an error.

Check if your arguments are valid. Also, see "Does this library sanitize invalid HTML?".

Does this library support SSR?

Yes, this library supports server-side rendering on Node.js. See demo.

Why are my elements nested incorrectly?

Make sure your HTML markup is valid. The HTML to DOM parsing will be affected if you're using self-closing syntax (/>) on non-void elements:

parse('<div /><div />'); // returns single element instead of array of elements

See #158.

I get "Warning: validateDOMNesting(...): Whitespace text nodes cannot appear as a child of table."

Enable the trim option. See #155.

Don't change case of tags.

Tags are lowercased by default. To prevent that from happening, pass the htmlparser2 option:

const options = {
  htmlparser2: {
    lowerCaseTags: false
parse('<CustomElement>', options); // React.createElement('CustomElement')

Warning: By preserving case-sensitivity of the tags, you may get rendering warnings like:

Warning: <CustomElement> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.

See #62 and example.


$ npm run test:benchmark

Here's an example output of the benchmarks run on a MacBook Pro 2017:

html-to-react - Single x 415,186 ops/sec ±0.92% (85 runs sampled)
html-to-react - Multiple x 139,780 ops/sec ±2.32% (87 runs sampled)
html-to-react - Complex x 8,118 ops/sec ±2.99% (82 runs sampled)


Code Contributors

This project exists thanks to all the people who contribute. [Contribute].

Code Contributors

Financial Contributors

Become a financial contributor and help us sustain our community. [Contribute]


Financial Contributors - Individuals


Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]

Financial Contributors - Organization 0 Financial Contributors - Organization 1 Financial Contributors - Organization 2 Financial Contributors - Organization 3 Financial Contributors - Organization 4 Financial Contributors - Organization 5 Financial Contributors - Organization 6 Financial Contributors - Organization 7 Financial Contributors - Organization 8 Financial Contributors - Organization 9





npm i html-react-parser

DownloadsWeekly Downloads






Unpacked Size

255 kB

Total Files


Last publish


  • avatar