HTML to Text Conversion
C# Programming
Text Processing
Coding Tutorial
Software Development

How can I Convert HTML to Text in C?

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Converting HTML to Plain Text in C#

Extracting plain text from HTML is a frequent need in applications like email processing, search indexing, web scraping, and content migration. C# offers several approaches, ranging from simple regular expressions to full-featured HTML parsing libraries. Each method has different tradeoffs in terms of accuracy, performance, and robustness against malformed markup.

This article walks through three practical approaches, with working code examples and guidance on when to use each one.

Approach 1: Regular Expressions

Using Regex.Replace to strip HTML tags is the quickest approach for simple cases. It works well when the input is predictable, well-formed HTML without embedded scripts or styles.

csharp
1using System;
2using System.Text.RegularExpressions;
3
4public static class HtmlStripper
5{
6    public static string StripTags(string html)
7    {
8        if (string.IsNullOrEmpty(html))
9            return string.Empty;
10
11        // Remove script and style blocks entirely
12        string cleaned = Regex.Replace(html, @"<(script|style)[^>]*>.*?</\1>",
13            string.Empty, RegexOptions.Singleline | RegexOptions.IgnoreCase);
14
15        // Remove all HTML tags
16        cleaned = Regex.Replace(cleaned, @"<[^>]+>", string.Empty);
17
18        // Decode common HTML entities
19        cleaned = System.Net.WebUtility.HtmlDecode(cleaned);
20
21        // Collapse multiple whitespace characters into a single space
22        cleaned = Regex.Replace(cleaned, @"\s+", " ").Trim();
23
24        return cleaned;
25    }
26}

Usage:

csharp
1string html = "<p>Hello <strong>world</strong>!</p><script>var x = 1;</script>";
2string text = HtmlStripper.StripTags(html);
3Console.WriteLine(text);
4// Output: Hello world!

Pros: No external dependencies. Fast for small, well-structured input.

Cons: Fails on nested tags, malformed HTML, and edge cases like tags split across lines. Not suitable for production use with untrusted input.

HtmlAgilityPack is a widely used .NET library that parses HTML into a DOM tree, similar to how a browser processes markup. It handles malformed HTML gracefully and provides full traversal capabilities.

Install it via NuGet:

bash
dotnet add package HtmlAgilityPack

Here is a robust conversion method:

csharp
1using System;
2using System.Text;
3using HtmlAgilityPack;
4
5public static class HtmlToTextConverter
6{
7    public static string Convert(string html)
8    {
9        if (string.IsNullOrEmpty(html))
10            return string.Empty;
11
12        var doc = new HtmlDocument();
13        doc.LoadHtml(html);
14
15        // Remove script and style nodes
16        foreach (var script in doc.DocumentNode.SelectNodes("//script|//style") 
17                 ?? new HtmlNodeCollection(null))
18        {
19            script.Remove();
20        }
21
22        var sb = new StringBuilder();
23        ExtractText(doc.DocumentNode, sb);
24
25        // Clean up whitespace
26        string result = System.Text.RegularExpressions.Regex.Replace(
27            sb.ToString(), @"[ \t]+", " ");
28
29        // Collapse multiple newlines into at most two
30        result = System.Text.RegularExpressions.Regex.Replace(
31            result, @"\n{3,}", "\n\n");
32
33        return result.Trim();
34    }
35
36    private static void ExtractText(HtmlNode node, StringBuilder sb)
37    {
38        if (node.NodeType == HtmlNodeType.Text)
39        {
40            string text = HtmlEntity.DeEntitize(node.InnerText);
41            if (!string.IsNullOrWhiteSpace(text))
42            {
43                sb.Append(text);
44            }
45            return;
46        }
47
48        // Add line breaks for block-level elements
49        bool isBlock = IsBlockElement(node.Name);
50        if (isBlock)
51            sb.AppendLine();
52
53        foreach (var child in node.ChildNodes)
54        {
55            ExtractText(child, sb);
56        }
57
58        if (isBlock)
59            sb.AppendLine();
60    }
61
62    private static bool IsBlockElement(string name)
63    {
64        return name switch
65        {
66            "p" or "div" or "br" or "hr" or "h1" or "h2" or "h3"
67            or "h4" or "h5" or "h6" or "li" or "tr" or "blockquote"
68            or "pre" or "section" or "article" => true,
69            _ => false
70        };
71    }
72}

Usage:

csharp
1string html = @"
2<html>
3<head><style>body { color: red; }</style></head>
4<body>
5    <h1>Welcome</h1>
6    <p>This is a <a href='#'>link</a> inside a paragraph.</p>
7    <ul>
8        <li>Item one</li>
9        <li>Item two</li>
10    </ul>
11</body>
12</html>";
13
14string text = HtmlToTextConverter.Convert(html);
15Console.WriteLine(text);

Output:

text
1Welcome
2This is a link inside a paragraph.
3Item one
4Item two

Pros: Handles malformed HTML, nested structures, and HTML entities correctly. Provides DOM traversal for fine-grained control.

Cons: Requires a third-party NuGet package.

Approach 3: AngleSharp

AngleSharp is a newer, standards-compliant HTML parser that follows the W3C specification. It is a good choice when you need browser-like parsing accuracy:

csharp
1using System;
2using System.Threading.Tasks;
3using AngleSharp;
4
5public static class AngleSharpConverter
6{
7    public static async Task<string> ConvertAsync(string html)
8    {
9        var config = Configuration.Default;
10        var context = BrowsingContext.New(config);
11        var document = await context.OpenAsync(req => req.Content(html));
12
13        // Remove script and style elements
14        foreach (var element in document.QuerySelectorAll("script, style"))
15        {
16            element.Remove();
17        }
18
19        return document.Body?.TextContent?.Trim() ?? string.Empty;
20    }
21}
csharp
1string html = "<p>Price: <span>$9.99</span></p>";
2string text = await AngleSharpConverter.ConvertAsync(html);
3Console.WriteLine(text);
4// Output: Price: $9.99

Pros: W3C-compliant parsing. Async API. Actively maintained with CSS selector support.

Cons: Slightly heavier dependency than HtmlAgilityPack. The async API adds complexity for simple synchronous use cases.

Common Pitfalls

  • Forgetting to remove script and style blocks. Simply stripping tags leaves the JavaScript and CSS content as visible text. Always remove these elements before extracting text.
  • Ignoring HTML entities. Raw text extraction without decoding produces strings like &amp; instead of &. Use HtmlEntity.DeEntitize (HtmlAgilityPack) or WebUtility.HtmlDecode (built-in) to decode entities.
  • Losing structural formatting. Stripping all tags without adding line breaks for block elements produces a wall of text. Insert newlines at paragraph, heading, and list-item boundaries to preserve readability.
  • Regex on untrusted HTML. Regular expressions cannot reliably parse HTML because HTML is not a regular language. Tags can contain attributes with > characters, nested comments, and CDATA sections that break simple patterns.
  • Performance on large documents. For documents larger than a few hundred kilobytes, avoid loading the entire string into a regex replacement. Stream-based parsing with HtmlAgilityPack or AngleSharp is more memory-efficient.

Summary

For quick, one-off conversions of simple HTML, regex-based stripping works. For anything beyond trivial input, use a proper HTML parser. HtmlAgilityPack is the most popular choice in the .NET ecosystem and handles malformed HTML well. AngleSharp offers W3C-compliant parsing with a modern async API. Regardless of the approach, always remove script and style elements first, decode HTML entities, and insert appropriate whitespace for block-level elements to produce readable plain text output.


Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.