HTML to JSONHTML Tables
Scrape tables from HTML.
Convert any HTML <table> element (from a file, a fetched page, or a string) into structured worksheet JSON, one worksheet per table. Supports data-formula attributes, merged cells (colspan/rowspan), and inline styles.
Tables on web pages, in HTML e-mails and in .html exports from reporting tools hold real data, but getting it out usually means writing a DOM scraper for each page. TabularJS turns every <table> into a worksheet with a 2D data array, the same structure it returns for an Excel file.
It accepts an HTML string (any string that starts with <), a DOM element in the browser, or an .html or .htm file as a path, File, Blob or bytes. The markup is parsed by a small JavaScript HTML parser, so it works in Node.js without jsdom or a headless browser.
Feature support
What TabularJS extracts from HTML files
- One worksheet per
<table>, namedTable1,Table2..., or a single table with thetableIndexoption. - Rows from
<thead>,<tbody>and<tfoot>in that order, with the trimmed text of each cell.<script>and<style>content is ignored. - The first row becomes the column titles in
columns[i].titleand is removed fromdata, unless you passfirstRowAsHeader: false. colspanandrowspaninmergeCellsas[colspan, rowspan]; the covered cells are empty strings.- The
styleattribute of each cell inworksheet.style(CSS strings), thetitleattribute incomments, anddata-formulaattributes as formula text with=.
Convert HTML to JSON in Node.js
import tabularjs from 'tabularjs';
// From a file
const result = await tabularjs('page.html');
const scores = result.worksheets[0];
console.log(scores.columns.map((c) => c.title)); // [ 'Name', 'Score' ]
console.log(scores.data);
// [ [ 'Alice', '90' ], [ 'Bob', '85' ], [ 'Total', '=SUM(B1:B2)' ], [ 'Final', '' ] ]
// From a fetched page: pass the HTML text, and pick the second table only
const response = await fetch('https://example.com/report.html');
const second = await tabularjs(await response.text(), { tableIndex: 1 });Read HTML files in the browser
import tabularjs from 'tabularjs';
// Convert a table that is already on the page
const table = document.querySelector('#scores');
const result = await tabularjs(table);
const sheet = result.worksheets[0];
const keys = sheet.columns.map((c) => c.title);
const records = sheet.data.map((row) => Object.fromEntries(keys.map((k, i) => [k, row[i]])));
console.log(records); // [ { Name: 'Alice', Score: '90' }, ... ]JSON output
{
"worksheets": [
{
"worksheetName": "Table1",
"data": [
["Alice", "90"],
["Bob", "85"],
["Total", "=SUM(B1:B2)"],
["Final", ""]
],
"columns": [{ "title": "Name", "width": 100 }, { "title": "Score", "width": 100 }],
"mergeCells": { "A4": [2, 1] },
"style": { "A1": "color: red" },
"comments": { "A1": "Top score" }
},
{
"worksheetName": "Table2",
"data": [],
"columns": [{ "title": "x", "width": 100 }, { "title": "y", "width": 100 }]
}
]
}Complete output for a page with two tables. The second table has a single row, which became the column titles, so its data is empty.
Options
| Option | Effect for HTML |
|---|---|
| tableIndex | Return only this table (0-based). The worksheet then has no worksheetName. An index past the last table throws an error. |
| firstRowAsHeader | Default true: the first row becomes the column titles and is removed from data. Set false to keep it as data, with titles A, B, C... |
Limitations
- Values are strings:
90is returned as'90'. - Only inline
styleattributes are kept; CSS from stylesheets and classes is not applied. - HTML files are read as UTF-8, and a page that has no
<table>throwsNo table elements found in HTML.
Frequently asked questions
How do I convert an HTML table to JSON in the browser?
Pass the element: await tabularjs(document.querySelector('table')). You get one worksheet with the header row in columns and the other rows in data.
Can I scrape a table from a URL in Node.js?
Fetch the page yourself and pass the HTML text: await tabularjs(await (await fetch(url)).text()). TabularJS does not download URLs, and pages that build their tables with JavaScript need a headless browser first.
How do I keep the first row as data?
Pass { firstRowAsHeader: false }. The first row stays in data and the columns get the titles A, B, C...
What happens to colspan and rowspan?
The value goes into the top-left cell, the covered cells are empty strings, and the span is recorded in mergeCells, for example { A4: [2, 1] } for a cell that spans two columns.
Why TabularJS for HTML Tables?
- No external spreadsheet parser dependencies: faster installs, smaller bundles.
- One API in Node.js and modern browsers.
- Output is shape-compatible withJspreadsheet: render parsed data in a live workbook with one call.