#2258·crawl4ai

[Bug]: DefaultTableExtraction drops <th> row headers and ignores rowspan, producing misaligned result.tables

Author: elokuuYHCreated Sep 13, 2026Updated Sep 14, 2026
Labels🐞 Bug⚙ Done
### crawl4ai version 0.9.3 ### Expected Behavior `result.tables[i]["rows"]` should match the logical grid a browser renders: - Row-header cells (`` inside ``) are kept as the first column. - A `rowspan` cell's value is repeated in every row it covers. - cells keep the current "repeat the value" behaviour, but the row must stay aligned with the header (no left shift, no phantom trailing ""). ### Current Behavior `DefaultTableExtraction.extract_table_data` only iterates `.//td` for body rows, so every `` inside `` is dropped: the remaining cells shift left and the last column is padded with "". `rowspan` is not handled at all. For manual documentation tables whose first column is a product / parameter name in ``, the whole key column disappears from `result.tables`. This is the follow-up to #2007: since v0.9.1 `rowspan`/`colspan` survive in `cleaned_html`, but the extractor does not use them. ### Is this reproducible? Yes ### Inputs Causing the Bug ```bash Any table with (a) `` cells in the body, or (b) a `rowspan` > 1 cell. Minimal HTML is in the steps below. ``` ### Steps to Reproduce ```bash 1. Run the script below (no browser, no crawl). 2. Compare the printed rows with the expected rows. ``` ### Code snippets ```python from lxml import html as lhtml from crawl4ai import DefaultTableExtraction HTML = """
Feature AFeature B
Item 1yesyes
Item 2noyes
GroupOption XOption Y
Group 1value xvalue y
note that applies to X and Y
""" root = lhtml.fromstring(HTML) for table in DefaultTableExtraction().extract_tables(root): print(table["headers"], table["rows"]) ``` ### OS windows 11 ### Python version 3.12 ### Browser N/A ### Browser version N/A ### Error logs & Screenshots (if applicable) Actual: ['', 'Feature A', 'Feature B'] [['yes', 'yes', ''], ['no', 'yes', '']] ['Group', 'Option X', 'Option Y'] [['Group 1', 'value x', 'value y'], ['note that applies to X and Y', 'note that applies to X and Y', '']] Expected: ['', 'Feature A', 'Feature B'] [['Item 1', 'yes', 'yes'], ['Item 2', 'no', 'yes']] ['Group', 'Option X', 'Option Y'] [['Group 1', 'value x', 'value y'], ['Group 1', 'note that applies to X and Y', 'note that applies to X and Y']] I'd like to submit a PR: expand rowspan/colspan into a rectangular grid (pending-cell map), collect `th|td` for body rows, and add unit tests for the cases above. The change is limited to `crawl4ai/table_extraction.py` plus a small shared grid helper; the scoring logic in `is_data_table` is untouched.