n8n Markdown Node
📝
Transform Node

n8n Markdown Node

Master the n8n Markdown node for converting between Markdown and HTML. Learn both conversion modes, formatting options, AI response processing, and report generation workflows.

Your AI just generated a perfectly formatted response, but it’s trapped in the wrong format. The ChatGPT output arrives as Markdown with headers, lists, and code blocks. You need it as HTML for an email. Or the opposite: you scraped a webpage and need clean Markdown for your RAG pipeline. The format mismatch breaks everything downstream.

The Markdown node solves this with two-way conversion between Markdown and HTML. No coding required. It handles GitHub Flavored Markdown, preserves code blocks, converts tables, and gives you control over exactly how the output renders. Whether you’re formatting AI responses for customers or preparing documents for language models, this node bridges the format gap.

The Format Conversion Challenge

Format mismatches create silent failures:

  • AI models output Markdown, but email clients need HTML
  • Web scraping returns HTML, but LLMs process Markdown better
  • Report generators expect HTML, but your data is in Markdown
  • CMS platforms have specific format requirements that don’t match your source

Manual conversion is tedious and error-prone. Copy-pasting through online converters breaks workflows. The Markdown node automates the transformation so your data flows seamlessly between systems.

What You’ll Learn

  • When to use the Markdown node versus alternatives
  • Both conversion modes: Markdown to HTML and HTML to Markdown
  • All configuration options for each mode
  • GitHub Flavored Markdown features and when to enable them
  • Processing AI/ChatGPT responses for emails and documents
  • Preparing content for RAG pipelines and vector databases
  • Creating HTML reports from structured data
  • Troubleshooting common conversion problems
  • Best practices for reliable format transformations

When to Use the Markdown Node

Before adding the node, confirm it’s the right tool for your task. The Markdown node handles format conversion, not content extraction or generation.

ScenarioUse Markdown Node?Alternative
Convert AI response to HTML for emailYesDirect solution
Convert scraped HTML to Markdown for LLMYesDirect solution
Generate HTML report from Markdown dataYesDirect solution
Extract specific data from HTMLNoHTML node
Create HTML from scratch with expressionsNoHTML node (Generate HTML Template)
Complex text manipulation with logicNoCode node
Simple string formattingNoExpressions with Edit Fields
PDF to text extractionNoExtract from File node

Rule of thumb: Use the Markdown node when you have complete content in one format that needs to become another format. For partial extraction, generation from data, or complex transformations, use other nodes.

When Not to Use the Markdown Node

The Markdown node converts entire content blocks. It doesn’t:

LimitationWhat HappensBetter Approach
Extract specific elements from HTMLConverts everything, not selectionsUse HTML node with CSS selectors
Handle mixed format contentTreats input as one formatSplit content first, then convert
Process binary filesExpects string inputExtract text first with Extract from File
Generate HTML with dynamic dataOnly converts existing contentUse HTML node’s template operation
Clean malformed HTMLMay produce unexpected outputClean HTML first with Code node

Understanding the Two Conversion Modes

The Markdown node operates in two distinct modes. Each uses a different parsing library optimized for its direction.

Markdown to HTML

Converts Markdown syntax into valid HTML. Uses the Showdown library, one of the most widely adopted Markdown parsers.

Input example:

# Welcome

This is **bold** and this is *italic*.

- Item one
- Item two

`inline code` and:

```javascript
const x = 1;
```

Output:

<h1>Welcome</h1>
<p>This is <strong>bold</strong> and this is <em>italic</em>.</p>
<ul>
<li>Item one</li>
<li>Item two</li>
</ul>
<p><code>inline code</code> and:</p>
<pre><code class="javascript language-javascript">const x = 1;
</code></pre>

Best for:

  • Formatting AI responses for email
  • Converting documentation for web display
  • Generating HTML snippets for CMS platforms
  • Creating formatted content for HTML-based systems

HTML to Markdown

Converts HTML content into clean Markdown syntax. Uses the node-html-markdown library, designed specifically for this conversion direction.

Input example:

<h1>Product Details</h1>
<p>This item is <strong>currently on sale</strong>.</p>
<ul>
  <li>Feature A</li>
  <li>Feature B</li>
</ul>
<a href="https://example.com">Learn more</a>

Output:

# Product Details

This item is **currently on sale**.

- Feature A
- Feature B

[Learn more](https://example.com)

Best for:

  • Preparing scraped content for LLM processing
  • Converting HTML emails to readable format
  • Creating Markdown documentation from web content
  • RAG pipeline document preparation

Quick Comparison

AspectMarkdown to HTMLHTML to Markdown
Parser libraryShowdownnode-html-markdown
Primary useDisplay/email formattingLLM/document preparation
Input formatMarkdown textHTML markup
Output formatHTML markupMarkdown text
GFM supportConfigurable optionsAutomatic handling
Code block handlingPreserves with language classConverts to fenced blocks

Your First Markdown Conversion

Let’s build a simple workflow that converts AI-generated Markdown to HTML for email.

Step 1: Add the Markdown Node

  1. Open your n8n workflow
  2. Click + to add a node
  3. Search for “Markdown”
  4. Select the Markdown node

Step 2: Configure the Mode

  1. Set Mode to “Markdown to HTML”
  2. The input field label changes to “Markdown”

Step 3: Provide Input Content

For testing, enter sample Markdown directly:

# Weekly Report

Here are this week's highlights:

- Completed **3 major features**
- Fixed *12 bugs*
- Deployed to production

## Next Steps

1. Review feedback
2. Plan sprint

Or reference data from a previous node:

{{ $json.aiResponse }}

Step 4: Test and Verify

Click Test step. The output appears in the data field (or your configured destination):

<h1>Weekly Report</h1>
<p>Here are this week's highlights:</p>
<ul>
<li>Completed <strong>3 major features</strong></li>
<li>Fixed <em>12 bugs</em></li>
<li>Deployed to production</li>
</ul>
<h2>Next Steps</h2>
<ol>
<li>Review feedback</li>
<li>Plan sprint</li>
</ol>

Step 5: Use the Output

Access the converted content in subsequent nodes:

{{ $json.data }}

Connect to an email node, HTTP Request, or any node that accepts HTML content.

Node Parameters Deep Dive

Understanding every parameter prevents conversion surprises.

Mode

ModeDescription
Markdown to HTMLConverts Markdown syntax to HTML markup
HTML to MarkdownConverts HTML markup to Markdown syntax

The mode you select determines which options appear below.

Input Field

For Markdown to HTML: Enter Markdown content directly or use an expression to reference data from previous nodes.

For HTML to Markdown: Enter HTML content directly or reference it with an expression.

Expression examples:

// Reference a specific field
{{ $json.content }}

// Reference nested data
{{ $json.response.message }}

// Reference from a named node
{{ $('AI Agent').item.json.output }}

Destination Key

By default, the converted output goes to a field called data. You can customize this:

SettingOutput Location
data (default)$json.data
htmlContent$json.htmlContent
body.content$json.body.content (nested)
results.formatted$json.results.formatted (nested)

Nested paths are powerful for organizing output alongside other data. The node creates the nested structure automatically.

Markdown to HTML Options

These options appear when Mode is set to “Markdown to HTML”. They control how specific Markdown features convert to HTML.

When enabled, adds target="_blank" to all links so they open in new tabs.

SettingOutput
Disabled<a href="...">Link</a>
Enabled<a href="..." target="_blank">Link</a>

Use when: Creating HTML for web pages or emails where you want external links to open separately.

Automatic Linking

Automatically converts URLs and email addresses to clickable links, even without Markdown link syntax.

Input:

Visit https://example.com or email [email protected]

Output (enabled):

<p>Visit <a href="https://example.com">https://example.com</a> or email <a href="mailto:[email protected]">[email protected]</a></p>

Use when: Processing content where URLs aren’t already formatted as links.

Emoji Support

Converts emoji shortcodes to actual emoji characters.

Input:

Great job! :thumbsup: :rocket:

Output (enabled):

<p>Great job! 👍 🚀</p>

Use when: Processing content from platforms that use GitHub-style emoji shortcodes.

Tables

Enables GitHub Flavored Markdown table syntax support.

Input:

| Name | Price |
| ---- | ----- |
| Item | $10   |

Output (enabled):

<table>
<thead>
<tr>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>Item</td>
<td>$10</td>
</tr>
</tbody>
</table>

Use when: Your Markdown contains tabular data. Most AI models output tables in this format.

GitHub Flavored Markdown (GFM)

Enables the full GFM specification, which includes:

  • Tables
  • Task lists (- [x] Done)
  • Strikethrough (~~text~~)
  • Autolinks
  • Disallowed raw HTML

Recommendation: Enable this for most use cases, especially when processing AI output. ChatGPT, Claude, and other models typically output GFM-compatible Markdown.

Task Lists

Converts checkbox syntax to HTML checkbox elements.

Input:

- [x] Completed task
- [ ] Pending task

Output (enabled):

<ul>
<li><input type="checkbox" checked disabled> Completed task</li>
<li><input type="checkbox" disabled> Pending task</li>
</ul>

Use when: Converting task lists or TODO items from AI responses or project management tools.

Strikethrough

Enables ~~strikethrough~~ syntax support.

Input:

The price is ~~$50~~ $30

Output (enabled):

<p>The price is <del>$50</del> $30</p>

Split Level

Controls how headers create document structure. Advanced option for specific formatting needs.

HTML to Markdown Options

These options appear when Mode is set to “HTML to Markdown”. They control the style of the generated Markdown.

Bullet List Marker

Choose the character for unordered lists.

OptionOutput
- (default)- Item
** Item
++ Item

Recommendation: Use - for compatibility with most Markdown parsers and AI models.

Code Block Style

Choose how code blocks render in the output.

OptionOutput
Fenced (default)```code```
IndentedFour-space indentation

Recommendation: Use Fenced for better readability and language specification support.

Emphasis Delimiter

Choose the character for italic text.

OptionOutput
_ (default)_italic_
**italic*

Heading Style

Choose how headers render in Markdown.

OptionOutput
ATX (default)# Heading
SetextHeading with underline (=== or ---)

Recommendation: Use ATX for cleaner, more consistent output. Setext only supports H1 and H2.

Choose how links render.

OptionOutput
Inlined (default)[text](url)
Referenced[text][1] with [1]: url at bottom

Recommendation: Use Inlined for simpler documents. Referenced is useful for documents with many repeated links.

Strong Delimiter

Choose the character for bold text.

OptionOutput
** (default)**bold**
____bold__

Real-World Examples

Example 1: Formatting AI Responses for Email

Scenario: ChatGPT generates a customer response in Markdown. You need HTML for an email.

Workflow:

Webhook → OpenAI Chat → Markdown (MD→HTML) → Send Email

Markdown Node Configuration:

  • Mode: Markdown to HTML
  • Markdown: {{ $json.message.content }}
  • Options:
    • Tables: Enabled
    • GFM: Enabled
    • Add Blank to Links: Enabled

Why this works: AI models output Markdown by default. The Markdown node converts it to email-ready HTML while preserving all formatting.

Example 2: Preparing Scraped Content for LLM Processing

Scenario: You scrape a webpage and need to feed it to an AI for summarization. HTML is noisy. Markdown is cleaner.

Workflow:

HTTP Request → HTML Extract → Markdown (HTML→MD) → AI Agent

Markdown Node Configuration:

  • Mode: HTML to Markdown
  • HTML: {{ $json.data }}
  • Destination Key: cleanContent
  • Options:
    • Code Block Style: Fenced
    • Heading Style: ATX

Why this works: Converting HTML to Markdown removes noise (tags, attributes) while preserving structure (headings, lists). This improves LLM comprehension and reduces token usage.

For more on optimizing AI workflows, see our guide to AI agents vs LLM chains.

Example 3: Generating HTML Reports from Data

Scenario: You have structured data and need to generate an HTML report.

Workflow:

Database → Code (generate MD) → Markdown (MD→HTML) → Convert to File → Email

Code Node (JavaScript):

const items = $input.all();
const data = items[0].json;

let markdown = `# Sales Report

## Summary

- Total Sales: **$${data.totalSales.toLocaleString()}**
- Orders: **${data.orderCount}**
- Average Order: **$${(data.totalSales / data.orderCount).toFixed(2)}**

## Top Products

| Product | Units | Revenue |
| ------- | ----- | ------- |
`;

data.topProducts.forEach(p => {
  markdown += `| ${p.name} | ${p.units} | $${p.revenue} |\n`;
});

return [{ json: { markdown } }];

Markdown Node Configuration:

  • Mode: Markdown to HTML
  • Markdown: {{ $json.markdown }}
  • Options:
    • Tables: Enabled
    • GFM: Enabled

The HTML output can then be converted to a file or embedded in an email.

Example 4: RAG Pipeline Document Preparation

Scenario: You’re building a RAG system. Documents arrive as HTML but need to be chunked effectively for vector storage.

Workflow:

HTTP Request → Markdown (HTML→MD) → Split (by headers) → Embeddings → Vector Store

Why Markdown for RAG:

Markdown preserves document structure (headers, lists, code blocks) while eliminating HTML noise. This structure helps the text splitter create meaningful chunks at logical boundaries.

Markdown Node Configuration:

  • Mode: HTML to Markdown
  • HTML: {{ $json.data }}
  • Options:
    • Heading Style: ATX (consistent # format for splitting)
    • Code Block Style: Fenced

Splitting strategy:

Use a text splitter that recognizes Markdown headers. Split at ## (H2) level to create topic-focused chunks that maintain context.

For comprehensive data transformation strategies, see our data transformation guide.

Example 5: Newsletter Content Formatting

Scenario: You aggregate content from multiple sources and need to format a newsletter.

Workflow:

RSS Feeds → Aggregate → Code (compile MD) → Markdown (MD→HTML) → Email

Code Node (JavaScript):

const items = $input.all();

let newsletter = `# This Week's Highlights

`;

items.forEach((item, i) => {
  const data = item.json;
  newsletter += `## ${i + 1}. ${data.title}

${data.summary}

[Read more](${data.link})

---

`;
});

newsletter += `

*Unsubscribe: [Click here]({{unsubscribeLink}})*
`;

return [{ json: { newsletter } }];

Markdown Node Configuration:

  • Mode: Markdown to HTML
  • Options:
    • Add Blank to Links: Enabled (opens in new tab)
    • GFM: Enabled

Working with AI Responses

AI models are the most common source of Markdown content in n8n workflows. Here’s how to handle them reliably.

Common AI Output Patterns

Most AI models (ChatGPT, Claude, Gemini) output responses in Markdown format:

Here's a summary of the document:

## Key Points

1. **First point** with details
2. **Second point** with more info

### Code Example

```python
def example():
    return "Hello"
```

Let me know if you need clarification.

For typical AI response processing:

OptionSettingWhy
TablesEnabledAI often outputs tabular data
GFMEnabledAI follows GFM conventions
Task ListsEnabledAI generates checklists
StrikethroughEnabledAI uses this for corrections
Add Blank to LinksEnabledSafer for email links

Preserving Code Blocks

AI responses often contain code. The Markdown node preserves code blocks with language specification:

Input:

Here's how to do it:

```javascript
const result = await fetch(url);
```

Output:

<p>Here's how to do it:</p>
<pre><code class="javascript language-javascript">const result = await fetch(url);
</code></pre>

The language-javascript class enables syntax highlighting if your display system supports it.

Handling Edge Cases

Problem: AI sometimes includes extra explanation before/after the actual content.

Solution: Use an Edit Fields node to extract just the relevant portion before conversion:

// Extract content between markers
{{ $json.response.match(/```markdown([\s\S]*?)```/)?.[1] || $json.response }}

Problem: AI outputs inconsistent heading levels.

Solution: Normalize in a Code node before conversion, or accept the inconsistency and style with CSS after conversion.

Troubleshooting Common Issues

Output Not Rendering Correctly

Symptom: HTML appears as plain text instead of formatted content.

Cause: The receiving system isn’t interpreting the content as HTML.

Solutions:

  1. Check if the email node’s content type is set to HTML
  2. Verify the destination system accepts HTML
  3. Wrap output in proper HTML document structure if needed:
{{ '<html><body>' + $json.data + '</body></html>' }}

Missing Tables in Output

Symptom: Table Markdown appears as plain text lines.

Cause: Tables option not enabled.

Solution: Enable the Tables option in Markdown to HTML mode.

Special Characters Breaking Conversion

Symptom: Characters like <, >, & cause issues.

Cause: These characters have special meaning in HTML.

For MD→HTML: The converter escapes these automatically. If you’re seeing issues, the input may already be partially HTML.

For HTML→MD: Ensure your input is valid HTML. Run it through a validator if needed.

Nested Content Problems

Symptom: Deeply nested lists or quotes don’t convert properly.

Cause: Parser limitations with complex nesting.

Solution: Simplify the structure before conversion, or use the Code node for complex transformations.

Inconsistent Line Breaks

Symptom: Line breaks appear differently than expected.

Cause: Markdown has specific rules for line breaks (two spaces at end of line, or blank line for paragraph).

Solution: Ensure your Markdown source follows standard line break conventions. Or post-process the HTML to add <br> where needed.

For workflow debugging help, try our workflow debugger tool.

Pro Tips and Best Practices

1. Test with Representative Content

Before deploying, test with actual content that matches your production data. Edge cases in real content often differ from simple test examples.

2. Chain Transformations Strategically

Complex transformations often work better as multiple steps:

Raw Data → Code (prepare) → Markdown (convert) → Edit Fields (clean)

Rather than trying to do everything in one node.

3. Consider Performance

The Markdown node processes content synchronously. For large documents or high-volume workflows:

  • Process items individually rather than concatenating into huge strings
  • Consider splitting very large documents before conversion
  • Monitor execution time with batch processing strategies

4. Validate Expressions

When using expressions to reference input content, ensure the field exists:

{{ $json.content || '' }}

This prevents errors when the field is undefined.

For expression validation, use our expression validator tool.

5. Use Destination Key for Clean Output

Rather than letting converted content overwrite your input, use a specific destination key:

Destination Key: convertedHtml

This preserves the original content alongside the converted version.

6. Document Your Options

When using specific options, add a sticky note explaining why:

Tables: ON - AI reports include pricing tables
GFM: ON - Standard for ChatGPT output

Future you (or your team) will appreciate the context.

7. Handle Empty Content

Add a check before conversion to avoid processing empty strings:

If Node → Check: {{ $json.content.length > 0 }}
  → True: Markdown Node
  → False: Skip/Default

When to Get Help

Some scenarios benefit from expert assistance:

  • Complex multi-format workflows with conditional conversion logic
  • High-volume processing requiring optimization
  • Integration with specific CMS platforms that have unique requirements
  • Custom Markdown extensions beyond standard GFM

Our workflow development services can build production-ready solutions. For architectural guidance, explore our n8n consulting services.

Frequently Asked Questions

What’s the difference between the Markdown node and using expressions for text formatting?

Expressions handle simple string operations. The Markdown node performs full document parsing and conversion.

Use expressions for:

  • String concatenation: {{ $json.first + ' ' + $json.last }}
  • Case changes: {{ $json.text.toUpperCase() }}
  • Number formatting: {{ $json.price.toFixed(2) }}

Use the Markdown node for:

  • Converting headers, lists, code blocks, and tables
  • Full Markdown-to-HTML or HTML-to-Markdown conversion
  • Preserving document structure during format changes

The key difference: expressions manipulate strings character by character. The Markdown node understands document structure and converts it properly.

Why isn’t my Markdown rendering correctly in Notion or Google Docs?

Notion and Google Docs don’t accept raw HTML. They have their own internal formats.

When you send converted HTML to these platforms, they treat it as plain text because they expect their native format, not HTML strings.

For Notion:

  • Use the Notion node’s native formatting options
  • Or use Notion’s Markdown import feature directly

For Google Docs:

  • Use the Google Docs API with proper document structure
  • HTML strings won’t render as formatted content

The Markdown node works well with:

  • Email clients (Gmail, Outlook, etc.)
  • Web pages and HTML-based CMS platforms
  • Any system that interprets HTML markup

How do I preserve code blocks when converting AI responses?

The Markdown node preserves code blocks automatically. Fenced code blocks convert to <pre><code> HTML tags with language classes intact.

Requirements for proper conversion:

  • Input must use fenced code blocks (triple backticks)
  • Language specification is preserved as a CSS class

If code isn’t converting properly:

  1. Check that the AI actually used fenced blocks (not just indentation)
  2. Prompt your AI: “Always use fenced code blocks with language specification”
  3. For HTML-to-Markdown, select “Fenced” code block style option

Example output:

<pre><code class="javascript language-javascript">const x = 1;</code></pre>

The language-javascript class enables syntax highlighting in systems that support it.

Can I convert partial HTML within a larger text block?

The Markdown node treats the entire input as one format. It cannot detect and convert only HTML portions within mixed content.

If you have mixed content, you have two options:

Option 1: Split and recombine

  1. Extract just the HTML portion using expressions or a Code node
  2. Convert it with the Markdown node
  3. Recombine with the other content

Option 2: Use a Code node

Write custom logic that handles mixed content using a parsing library.

Best practice: Restructure your workflow to keep formats separate. This is cleaner and more maintainable than trying to handle mixed content in a single field.

Which GFM options should I enable for typical use cases?

Different use cases need different options enabled.

For AI/ChatGPT output processing:

  • Tables: Enabled
  • GFM (main toggle): Enabled
  • Task Lists: Enabled
  • Strikethrough: Enabled

For basic documentation conversion:

  • Tables: Enabled
  • GFM: Enabled

For email content:

  • All above options
  • Add Blank to Links: Enabled (opens links in new tabs)

Emoji option:

  • Enable only if content uses shortcodes (:thumbsup: format)
  • Leave disabled if content uses Unicode emoji (👍) directly

Ready to Automate Your Business?

Tell us what you need automated. We'll build it, test it, and deploy it fast.

âś“ 48-72 Hour Turnaround
âś“ Production Ready
âś“ Free Consultation
⚡

Create Your Free Account

Sign up once, use all tools free forever. We require accounts to prevent abuse and keep our tools running for everyone.

or

By signing up, you agree to our Terms of Service and Privacy Policy. No spam, unsubscribe anytime.