Acquire / file · All operations
Read tables from an HTML page
A variant of Read an XML or HTML file
Pull the tables, or elements picked by CSS selector, out of an HTML page as rows.
Status
- In arcform
Not built yet
arcform does not do this yet. Its place on the roadmap
What other tools call it
Meridian's classification; an independent blind rating agreed on 95.7% of 324 rows (variant, version 3).
Duckle (1)
HTMLread 2026-09-25rows from an HTML page or table by CSS selector
Power Query M (2)
Html.Tableread 2026-09-27Build a table from HTML by running a CSS selector per column, with an optional row selector
Web.Pageread 2026-09-27Break an HTML document into its tables and other structures, plus its text with tags removed
VisiData (1)
html (loader)read 2026-09-23Load HTML tables, one sheet per table; also filetype htm
Background
In pandas, read_html finds the table elements in a Hypertext Markup Language (HTML) document and parses their rows and columns into tables, called DataFrames.[1][2] In HTML, the table element represents tabular data: information presented in a two-dimensional table of rows and columns of cells containing data.[3]
When to use it
Scraping a web page involves fetching it and then extracting data from it, and the page's data may then be copied into a spreadsheet or loaded into a database.[4] HTML is often assisted by Cascading Style Sheets (CSS), and CSS selectors target HTML elements by their type, attributes, current states and position in the document.[2][5] Read whole tables when the page marks its data up as a table, and pick elements by selector when the data sits in lists, cards or repeated blocks that are not tables. (Meridian's view)
In pandas, read_html returns every table on a page by default, and its match option keeps only the tables whose text matches a given string or regular expression.[1] In pandas, read_html builds the header from the table's thead element when it has one, and otherwise from rows that hold only th cells.[1] In pandas, read_html attempts to properly handle colspan and rowspan attributes.[1] In pandas, read_html assumes as little as possible about a table's structure, so some cleanup afterwards, such as assigning column names by hand, is to be expected.[1] Check any table with merged or stacked header cells by eye after reading it, because the column names are where a reader's guesses show first. (Meridian's view) In pandas, read_html has a displayed_only option, on by default, that decides whether elements styled display: none are parsed.[1]
Driving a web browser with a program such as Selenium or Playwright is especially useful for scraping dynamic sites, since the browser fully loads each page.[4] In Power Query M, Web.BrowserContents returns the HTML for a URL as viewed by a web browser.[6]
Tag soup is a pejorative for HTML written for a web page that is syntactically or structurally incorrect.[7] Tag soup encompasses common authoring mistakes such as malformed tags, improperly nested elements and unescaped ampersands.[7] All major web browsers currently have a tag soup parser for interpreting malformed HTML, with most error-handling elements standardised.[7] In pandas, the lxml parser makes no guarantees about its results unless it is given strictly valid markup, and read_html falls back to html5lib when lxml fails to parse.[8] In pandas, html5lib is far more lenient than lxml and generates valid HTML5 markup from invalid markup, though that does not make the result correct, since fixing markup has no single definition.[8]
The method
In pandas, read_html searches for table elements and, within each table, only for tr and th rows and the td elements inside them.[1] In VisiData, the HTML loader parses a page with lxml and opens it as an index of sheets, one for each table element, plus a sheet of the page's links.[9] In VisiData's HTML loader, the names from stacked header rows are joined with underscores into a single column name.[9]
The CSS selectors module defines more than 60 selectors and five combinators, and combinators select elements by their relationship to other elements.[5] The DuckDB community extension html_query queries HTML with CSS selectors, returning the first matching element or a list of all matching elements.[10] In html_query, an extract parameter chooses what comes back from each match: the element's full HTML when omitted, its inner text, or any attribute such as href.[10]
Compared with the alternatives
Many of the Extensible Markup Language (XML) processing libraries and tools that adopted XML Path Language (XPath) also offer CSS selectors, another World Wide Web Consortium (W3C) standard, as a simpler alternative.[11] In data mining, a program that detects the template behind similar pages from a source, extracts their content and translates it into a relational form is called a wrapper.[4] Reading a page's own tables is the gentlest kind of scraping: the page has already arranged the data into rows and columns, so no template has to be inferred. (Meridian's view)
Sources
- [1]pandas.read_html — pandas 3.1.1 documentationdocumentation
- [2]HTML - Wikipediasecondary source
- [3]<table> HTML table element - HTML | MDNdocumentation
- [4]Web scraping - Wikipediasecondary source
- [5]CSS selectors - CSS | MDNdocumentation
- [6]Accessing data functions - PowerQuery M | Microsoft Learndocumentation
- [7]Tag soup - Wikipediasecondary source
- [8]IO tools (text, CSV, HDF5, …) — pandas 3.1.1 documentationdocumentation
- [9]visidata/visidata/loaders/html.py at 7609212ec2febafa9caba7183cbebfaf49627909 · saulpw/visidata · GitHubdocumentation
- [10]html_query – DuckDB Community Extensionsdocumentation
- [11]XPath - Wikipediasecondary source