Web Development•7 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?
- Security: Prevent XSS attacks
- Text extraction: Get plain text from HTML content
- Search indexing: Index clean text
- Email: Convert HTML emails to plain text
- 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 -->
<script>alert('xss')</script>
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
- HTML Strip Tags - Remove HTML tags
- HTML Encode - Encode HTML entities
- HTML Decode - Decode HTML entities
Conclusion
Always use proper sanitization libraries for security-critical applications. Simple regex solutions work for trusted content but can be bypassed by malicious input.