Extract HTML Tables in C#

To extract HTML tables from files or URLs in C#, load the document with HTMLDocument, select one table with QuerySelector() or all tables with QuerySelectorAll(), read rows and cells, and save the values as CSV or TXT.

HTML tables are often used for schedules, reports, comparison pages, conversion matrices, invoices, and reference data. Aspose.HTML for .NET lets you load an HTML file or web page, inspect the DOM, select table elements with CSS selectors, and extract rows and cells for further processing in C# applications.

This article shows how to extract table data from HTML files or web page URLs, preserve header cells, export rows to a CSV file, save all page tables to a text report, and read links stored inside table cells.

Extract Table Data from HTML

Table extraction starts with the table structure itself: select a <table> element, iterate through its rows, and read the header and data cells in each row. Once the values are collected, you can save them to CSV, TXT, JSON, a database, or another format required by your application.

The following example uses the source file product-table.html. The file contains one HTML conversion task table with visible cell borders, so you can inspect the source table in a browser before extracting rows and cells from it. This sample writes the extracted values to CSV, but the DOM traversal part is the same for other output formats.

To extract table data from HTML in C#:

  1. Load the source HTML document with the HTMLDocument class.
  2. Use QuerySelector("table") to select the first table in the document.
  3. Use GetElementsByTagName(“tr”) to collect table rows as an HTMLCollection.
  4. For each row, use QuerySelectorAll(“th, td”) to read header and data cells as a NodeList.
  5. Read the cell TextContent and trim extra whitespace.
  6. Store the extracted values in the output format you need. This example writes rows to a .csv file.
 1using Aspose.Html;
 2using Aspose.Html.Collections;
 3using Aspose.Html.Dom;
 4using System;
 5using System.Collections.Generic;
 6using System.IO;
 7
 8string inputPath = Path.Combine(DataDir, "product-table.html");
 9string outputPath = Path.Combine(OutputDir, "product-table.csv");
10
11using (HTMLDocument document = new HTMLDocument(inputPath))
12{
13    // Select the first table in the document.
14    Element table = document.QuerySelector("table");
15    if (table == null)
16    {
17        Console.WriteLine("The target table was not found.");
18        return;
19    }
20
21    HTMLCollection rows = table.GetElementsByTagName("tr");
22    List<string> csvLines = new List<string>();
23
24    foreach (Element row in rows)
25    {
26        // Read both header and data cells from the current row.
27        NodeList cells = row.QuerySelectorAll("th, td");
28        List<string> values = new List<string>();
29
30        foreach (Element cell in cells)
31        {
32            values.Add(cell.TextContent.Trim());
33        }
34
35        if (values.Count > 0)
36        {
37            csvLines.Add(string.Join(",", values));
38        }
39    }
40
41    File.WriteAllLines(outputPath, csvLines);
42}

The example loads the HTML document, selects the first table, reads all rows, and stores each row as a list of cell values. The final line writes those rows to product-table.csv. If the document contains several tables, use a more specific selector such as main table, article table, or a stable table attribute. For production CSV export, add value escaping if table cells may contain commas, quotation marks, or line breaks.

Extract All Tables from a Web Page URL

Use a URL-based HTMLDocument constructor when tables should be extracted directly from a web page. Unlike the local CSV example, this workflow processes every matched table and saves a readable text report.

This example uses a placeholder URL. Replace https://docs.aspose.com/html/net/edit-html-document/ with the web page you want to inspect. If the page contains layout tables or unrelated comparison blocks, make the selector more specific, for example main table or article table.

To extract all tables from a web page URL in C#:

  1. Pass the page URL to the HTMLDocument(Url) constructor.
  2. Use QuerySelectorAll("table") to collect all table elements on the page.
  3. For each table, read rows with GetElementsByTagName("tr").
  4. For each row, read header and data cells with QuerySelectorAll("th, td").
  5. Save table numbers, row numbers, and cell text to a .txt file.
 1using Aspose.Html;
 2using Aspose.Html.Collections;
 3using Aspose.Html.Dom;
 4using System;
 5using System.Collections.Generic;
 6using System.IO;
 7
 8Url pageUrl = new Url("https://docs.aspose.com/html/net/edit-html-document/");
 9string outputPath = Path.Combine(OutputDir, "web-tables.txt");
10
11using (HTMLDocument document = new HTMLDocument(pageUrl))
12{
13    // Select every table available in the loaded DOM.
14    NodeList tables = document.QuerySelectorAll("table");
15    int tableIndex = 1;
16
17    using (StreamWriter writer = new StreamWriter(outputPath))
18    {
19        foreach (Element table in tables)
20        {
21            // Label each table before writing its rows.
22            writer.WriteLine("Table " + tableIndex);
23
24            HTMLCollection rows = table.GetElementsByTagName("tr");
25            int rowIndex = 1;
26
27            foreach (Element row in rows)
28            {
29                NodeList cells = row.QuerySelectorAll("th, td");
30                List<string> values = new List<string>();
31
32                foreach (Element cell in cells)
33                {
34                    values.Add(cell.TextContent.Trim());
35                }
36
37                if (values.Count > 0)
38                {
39                    writer.WriteLine("Row " + rowIndex + ": " + string.Join(" | ", values));
40                    rowIndex++;
41                }
42            }
43
44            writer.WriteLine();
45            tableIndex++;
46        }
47    }
48}

The text output is convenient for inspection, logging, and quick validation because it labels each table and row and separates cell values with |. Before relying on a selector in production, inspect the loaded DOM and confirm that the required tables exist in the HTML returned to Aspose.HTML. If a table is injected later by complex client-side scripts, it may not be available as ordinary source HTML.

Table cells may contain more than plain text. For example, a comparison table can include product links, download links, documentation links, or report URLs. In this case, TextContent gives the link text, while GetAttribute(“href”) gives the target URL.

The following example uses table-links.html, extracts links from any table cells in the document, and saves anchor text with URL values to a text file. It does not depend on a table id or class; the selector targets links only when they are inside table cells.

To extract links from HTML table cells in C#:

  1. Load the HTML document that contains the table.
  2. Use QuerySelectorAll("table td a[href], table th a[href]") to find links inside table cells.
  3. Iterate through the returned NodeList.
  4. Read link text with TextContent.
  5. Read the destination URL with GetAttribute("href").
  6. Save or process the extracted link records.
 1using Aspose.Html;
 2using Aspose.Html.Collections;
 3using Aspose.Html.Dom;
 4using System.Collections.Generic;
 5using System.IO;
 6
 7string inputPath = Path.Combine(DataDir, "table-links.html");
 8string outputPath = Path.Combine(OutputDir, "table-links.txt");
 9
10using (HTMLDocument document = new HTMLDocument(inputPath))
11{
12    // Find links only when they appear inside table header or data cells.
13    NodeList links = document.QuerySelectorAll("table td a[href], table th a[href]");
14    List<string> lines = new List<string>();
15
16    foreach (Element link in links)
17    {
18        string text = link.TextContent.Trim();
19        string href = link.GetAttribute("href");
20
21        lines.Add(text + " -> " + href);
22    }
23
24    File.WriteAllLines(outputPath, lines);
25}

Use this approach when table text is not enough and the original link target must be preserved for reporting, crawling, validation, or migration workflows. If you need links only from a specific content area, narrow the selector, for example article table td a[href].

Choose Selectors for Table Extraction

The selector should match the extraction scope. Use a broad selector when the document is simple, and narrow it when the page contains navigation, layout tables, related content, or several data tables.

TaskSelectorUse when
Extract the first tabletable with QuerySelector()The document contains one main data table.
Extract all tablestable with QuerySelectorAll()You need every table from a page or report.
Extract tables only from main contentmain table or article tableThe page also contains navigation, layout, footer, or related-content tables.
Extract rows after selecting a tabletrYou already have the target table element.
Extract header and data cellsth, tdYou need both column names and row values.
Extract links from table cellstable td a[href], table th a[href]Table cells contain anchor text and URLs.

Common HTML Table Extraction Issues

IssueCauseFix
No table is foundThe selector does not match the loaded HTML, or the table is produced dynamically by scripts.Inspect the HTML loaded by HTMLDocument and adjust the selector to the actual DOM.
CSV columns are shiftedThe source table uses rowspan or colspan.Add custom logic that expands spanned cells into a normalized grid before writing CSV.
Link URLs are missingOnly TextContent was extracted from the cell.Select nested <a> elements and read GetAttribute("href") when URLs must be preserved.
Extra whitespace appears in cellsTable cells contain line breaks, indentation, or nested inline elements.Normalize TextContent before saving extracted values.
Wrong table is extractedThe page contains navigation, layout, or nested tables before the target data table.Use a more specific selector, such as an ID, class, heading context, or parent container.

FAQ

Can Aspose.HTML for .NET extract tables from a web page URL?

Yes. Use the HTMLDocument(Url) constructor to load a web page, then use QuerySelectorAll("table") when you need to process every table on the page.

How do I preserve table headers in the extracted data?

Read both th and td elements when processing rows. Header cells can be written as the first CSV row or stored separately as column names.

Does this handle tables created by JavaScript?

Aspose.HTML works with the document available after loading. If a table is injected later by complex client-side scripts or external browser automation, inspect the loaded DOM first and make sure the table exists before extraction.

Related Data Extraction Articles

The complete C# examples and data files are available in the Aspose.HTML for .NET GitHub repository.