Utility Coder
← Back to Blog
Web Development7 min read

HTML Strip Tags: Remove HTML from Text Safely

Learn to strip HTML tags from text securely. Understand sanitization, XSS prevention, and text extraction techniques.

By Andy Pham

HTML Strip Tags: Remove HTML from Text Safely

Stripping HTML tags is essential for text extraction, security, and content processing. This guide covers safe methods and best practices.

Why Strip HTML Tags?

  1. Security: Prevent XSS attacks
  2. Text extraction: Get plain text from HTML content
  3. Search indexing: Index clean text
  4. Email: Convert HTML emails to plain text
  5. Preview generation: Create text summaries

Basic Techniques

JavaScript - Browser

// Method 1: DOMParser (safest for untrusted input)
function stripHtml(html) {
  const doc = new DOMParser().parseFromString(html, 'text/html');
  return doc.body.textContent || '';
}

// Method 2: Temporary element
function stripHtmlElement(html) {
  const temp = document.createElement('div');
  temp.innerHTML = html;
  return temp.textContent || temp.innerText || '';
}

// Method 3: Regex (not recommended for complex HTML)
function stripHtmlRegex(html) {
  return html.replace(/<[^>]*>/g, '');
}

JavaScript - Node.js

// Using striptags library
const striptags = require('striptags');
const text = striptags('<p>Hello <b>World</b></p>'); // "Hello World"

// Allow certain tags
const safe = striptags(html, ['p', 'br', 'b', 'i']);

// Using sanitize-html for more control
const sanitizeHtml = require('sanitize-html');
const clean = sanitizeHtml(html, {
  allowedTags: [],
  allowedAttributes: {}
});

PHP

<?php
// Built-in function
$text = strip_tags('<p>Hello <b>World</b></p>'); // "Hello World"

// Allow certain tags
$text = strip_tags($html, '<p><br>');

// More thorough cleaning
$text = strip_tags(html_entity_decode($html));
?>

Python

from bs4 import BeautifulSoup
import re

# Using BeautifulSoup (recommended)
def strip_html(html):
    soup = BeautifulSoup(html, 'html.parser')
    return soup.get_text()

# Using regex (simple cases)
def strip_html_regex(html):
    return re.sub(r'<[^>]+>', '', html)

# With html.parser
from html.parser import HTMLParser

class MLStripper(HTMLParser):
    def __init__(self):
        super().__init__()
        self.text = []

    def handle_data(self, data):
        self.text.append(data)

    def get_text(self):
        return ''.join(self.text)

Advanced Stripping

Preserve Line Breaks

function stripHtmlPreserveBreaks(html) {
  // Replace block elements with newlines
  let text = html
    .replace(/<brs*/?>/gi, '
')
    .replace(/</p>/gi, '

')
    .replace(/</div>/gi, '
')
    .replace(/</h[1-6]>/gi, '

');

  // Strip remaining tags
  text = text.replace(/<[^>]+>/g, '');

  // Clean up whitespace
  return text.replace(/
{3,}/g, '

').trim();
}

Extract Text with Structure

function extractStructuredText(html) {
  const doc = new DOMParser().parseFromString(html, 'text/html');
  const result = [];

  function walk(node, depth = 0) {
    if (node.nodeType === Node.TEXT_NODE) {
      const text = node.textContent.trim();
      if (text) result.push({ text, depth });
    } else if (node.nodeType === Node.ELEMENT_NODE) {
      const tag = node.tagName.toLowerCase();
      const isBlock = ['p', 'div', 'h1', 'h2', 'h3', 'li'].includes(tag);

      for (const child of node.childNodes) {
        walk(child, isBlock ? depth + 1 : depth);
      }
    }
  }

  walk(doc.body);
  return result;
}

Security Considerations

XSS Prevention

// DANGEROUS - Never do this with untrusted input
element.innerHTML = userInput; // XSS vulnerability!

// SAFE - Strip tags first
const safe = stripHtml(userInput);
element.textContent = safe;

// Or use a sanitizer
const clean = DOMPurify.sanitize(userInput);
element.innerHTML = clean;

Common Attack Vectors

<!-- These bypass simple regex strippers -->
<script>alert('xss')</script>
<img src=x onerror=alert('xss')>
<svg onload=alert('xss')>
<a href="javascript:alert('xss')">click</a>
<div style="background:url(javascript:alert('xss'))">

<!-- Encoded attacks -->
&lt;script&gt;alert('xss')&lt;/script&gt;

Robust Sanitization

// Using DOMPurify (recommended)
const DOMPurify = require('dompurify');

// Strip all tags
const text = DOMPurify.sanitize(html, {
  ALLOWED_TAGS: [],
  ALLOWED_ATTR: []
});

// Allow safe subset
const safe = DOMPurify.sanitize(html, {
  ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'p', 'br'],
  ALLOWED_ATTR: []
});

Use Cases

1. Search Preview

function createPreview(html, maxLength = 160) {
  const text = stripHtml(html);
  if (text.length <= maxLength) return text;
  return text.substring(0, maxLength - 3) + '...';
}

2. Word Count

function countWords(html) {
  const text = stripHtml(html);
  return text.split(/s+/).filter(w => w.length > 0).length;
}

3. Email Plain Text Version

function htmlToPlainEmail(html) {
  let text = html
    .replace(/<a[^>]*href="([^"]*)"[^>]*>([^<]*)</a>/gi, '$2 ($1)')
    .replace(/<brs*/?>/gi, '
')
    .replace(/</p>/gi, '

');

  return stripHtml(text).trim();
}

Try Our Tools

Conclusion

Always use proper sanitization libraries for security-critical applications. Simple regex solutions work for trusted content but can be bypassed by malicious input.

Share this article