Skip to content

Guide · Open source

How to use Turndown: convert HTML to Markdown in JavaScript

Updated · written with AI from the project's own documentation and checked against our catalogue data

Turndown is a JavaScript library that takes HTML and returns Markdown text. It runs in Node.js or in a web page, so it fits any project that needs a JavaScript-only HTML-to-Markdown step. This guide shows you how to install it, run a first conversion, set output options, and extend it with custom rules and plugins.

Turndownmixmark-io/turndown · ★ 11.5k · MIT

Quick start

  1. 1Install the package. Run npm install turndown in your project folder. Node.js is required.
  2. 2Require the library. In Node.js, load it with require('turndown'), or include the browser script from unpkg in a web page.
  3. 3Create an instance. Call new TurndownService() with optional settings such as headingStyle or codeBlockStyle.
  4. 4Convert your HTML. Pass an HTML string or a DOM node to the turndown() method to get Markdown text back.
  5. 5Add rules or plugins. Use addRule(), keep() or remove() for custom handling, or use() with turndown-plugin-gfm for tables and strikethrough.
  6. 6Check the output. Review the Markdown, especially escaped characters, before using it in production.

Install Turndown with npm or a browser script tag

Turndown is installed through the npm package manager. The README lists Node.js as the prerequisite, but does not specify a required version.

For browser use, the README gives a script tag that loads Turndown from unpkg. For RequireJS, UMD builds are provided in lib/turndown.umd.js (Node.js) and lib/turndown.browser.umd.js (browser).

npm install turndown

Convert HTML to Markdown with your first script

Create a TurndownService instance and pass it an HTML string. The method returns the Markdown as a string.

Turndown also accepts DOM nodes: element nodes, document nodes, or document fragment nodes. This is useful in a browser when you want to convert content already on the page.

// For Node.js var TurndownService = require('turndown') var turndownService = new TurndownService() var markdown = turndownService.turndown('<h1>Hello world!</h1>') // In a browser, pass a DOM node var markdown = turndownService.turndown(document.getElementById('content'))

Set conversion options in the constructor

Pass an options object to the constructor to change the output style. The README lists these options with their valid values and defaults. Examples include headingStyle (setext or atx, default setext), bulletListMarker (-, +, or *, default *), codeBlockStyle (indented or fenced, default indented), and linkStyle (inlined or referenced, default inlined).

Advanced options blankReplacement, keepReplacement and defaultReplacement take rule replacement functions.

  • headingStyle: setext or atx (default setext)
  • bulletListMarker: -, + or * (default *)
  • codeBlockStyle: indented or fenced (default indented)
  • fence: ``` or ~~~ (default ```)
  • emDelimiter: _ or * (default _)
  • strongDelimiter: ** or __ (default **)
  • linkStyle: inlined or referenced (default inlined)
  • linkReferenceStyle: full, collapsed or shortcut (default full)
  • hr: any thematic break (default * * *)
  • preformattedCode: false or true (default false)
var turndownService = new TurndownService({ headingStyle: 'atx', codeBlockStyle: 'fenced' })

Keep, remove or customise elements with rules

By default Turndown does not keep or remove any elements. keep(filter) renders matching elements as HTML in the output, and remove(filter) deletes matching elements and their contents. Both return the instance, so calls can be chained.

For full control, addRule(key, rule) takes a rule object with a filter (a tag name, an array of tag names, or a function) and a replacement function. Rules are checked in a fixed order: blank rule, added rules, CommonMark rules, keep rules, remove rules, then the default rule. Added rules override CommonMark rules, but the blank rule runs before them.

  • Use keep() for elements you want to pass through as HTML.
  • Use remove() for elements that should disappear completely.
  • Use addRule() when you need a custom Markdown output for a tag.
turndownService.addRule('strikethrough', { filter: ['del', 's', 'strike'], replacement: function (content) { return '~' + content + '~' } }) turndownService.keep(['del', 'ins']) turndownService.remove('del')

Add GitHub-flavored Markdown with plugins

Plugins are functions called with the TurndownService instance. Use the use() method to apply one plugin or an array of plugins. The README points to the turndown-plugin-gfm package for GitHub-flavored Markdown tables and strikethrough.

The README shows importing the whole gfm bundle, or only the tables and strikethrough pieces.

var turndownPluginGfm = require('turndown-plugin-gfm') var gfm = turndownPluginGfm.gfm var tables = turndownPluginGfm.tables var strikethrough = turndownPluginGfm.strikethrough turndownService.use(gfm) // or only some features turndownService.use([tables, strikethrough])

Know the escaping behaviour before you rely on round trips

Turndown escapes Markdown characters with backslashes so they are not read as Markdown later. For example, the text 1. Hello world inside a heading is escaped as 1\. Hello world so it stays a heading rather than becoming a list item.

The README says these escaping rules use regular expressions and can be quite aggressive. If you need exact round-trip fidelity, test your content first. The README also notes an Overriding section for changing this behaviour.

What people use it for

  • Converting rich text editor output into Markdown for storage or publishing.
  • Turning web page content in a browser into Markdown inside a JavaScript app.
  • Applying custom Markdown output for specific tags, such as strikethrough with ~ delimiters.
  • Adding GitHub-flavored tables and strikethrough to converted content with turndown-plugin-gfm.

Frequently asked questions

How do I install Turndown?

Run npm install turndown in your project. The README also provides a browser script tag from unpkg and UMD builds for RequireJS.

What do I need to run Turndown?

The README lists Node.js as the prerequisite but does not specify a version. It can also run in a web page using the browser build.

Is Turndown free to use?

Turndown is released under the MIT licence, as shown on its project page. Check the licence file in the repository for the full terms.

Can Turndown convert Markdown back into HTML?

No. The README covers only HTML-to-Markdown conversion. You would need a different library for the reverse direction.

How do I keep some HTML tags in the output instead of converting them?

Use turndownService.keep() with the tag names, for example keep(['del', 'ins']). Those elements are then rendered as HTML in the Markdown output.

Why does my Markdown have extra backslashes?

Turndown escapes Markdown characters with backslashes, and the README says these rules can be quite aggressive. This is intended to keep text from being read as Markdown syntax. Test your typical content before relying on it.

New agent skills, repos and AI tools — every week

The best new skills and open-source projects, the fastest-growing repos, and one free prompt. Five minutes to read. Unsubscribe anytime.

Our verdict

Turndown suits developers who need a JavaScript-only HTML-to-Markdown step in Node.js or the browser, especially with custom tag rules or GFM tables through a plugin. It is not a fit for non-programmers who want a point-and-click tool, for Markdown-to-HTML conversion, or for projects that require exact round-trip fidelity.

Install options & downloads