DEV Community

Cover image for I built a browser extension that exports any web table to CSV, Excel, or Markdown — processed entirely on your device
Hudson Enterprises
Hudson Enterprises

Posted on

I built a browser extension that exports any web table to CSV, Excel, or Markdown — processed entirely on your device

There is a table on almost every page I work with — government data portals, Wikipedia, SaaS analytics dashboards, documentation sites. The standard workflow for getting that data somewhere useful is: select all, copy, paste into a spreadsheet, spend five minutes fixing the formatting. Or pay a monthly subscription for an export format you need twice a week.

I priced the segmentation as "your problem, not mine" and built a flat one-time alternative. That is the entire reason this exists.


How it works

Click the extension icon on any page. The extension reads the <table> elements from the DOM — the same data your browser already downloaded and rendered. You pick which table (the popup lists all detected tables with a mini-preview and their dimensions), pick a format, and the file is written to disk.

Nothing leaves your device during that process.

SheetJS (xlsx) handles XLSX generation entirely in the browser. The library is bundled inside the extension — not loaded from a CDN at runtime — so the network tab stays empty when you export. CSV and Markdown are pure JavaScript over the DOM structure, no dependencies.

License validation (when you activate a key) makes one call to api.lemonsqueezy.com. That is the only external network request the extension ever makes.


Three file formats — why each one

Different consumers want different things from the same table.

Format When you want it
CSV Data pipeline, pandas, any spreadsheet
XLSX Send to a non-technical colleague, need column widths or sheet structure
Markdown Documentation, GitHub issues, Obsidian notes, PRs

Copy to clipboard is also there for pasting directly into Slack, email, or a text field. That covers the full range of "I have a table on this page, I need it somewhere else."


What it handles — and what it doesn't

It handles standard HTML <table> elements. Most data tables on government sites, Wikipedia, documentation pages, and SaaS dashboards use standard table markup.

What it does not handle:

  • CSS grid / flexbox "tables" — if there is no <table> element in the DOM, there is nothing to read
  • Virtualized tables — enterprise dashboards that only render visible rows in the DOM; the extension captures the rendered rows, not the full dataset
  • Pages that block extensionschrome:// URLs and the Chrome Web Store itself block extension scripting by design

I document these in the extension's help text. I would rather a user know upfront what to expect than discover it on a page that matters.


The trial and price

Seven-day free trial, no account needed — the trial runs locally in the extension's storage. After that, it is $9 one-time. No subscription. All three export formats on day one.

The extension is live on the Chrome Web Store. The product page is at tableexporter.hudsonenterprisesllc.com.


What I learned building it

A few things that came up during the build worth sharing:

SheetJS in a Chrome extension (MV3) — bundling xlsx.full.min.js as a local vendor file is the right call. Loading from a CDN would break the "nothing transmitted" guarantee and also fails under strict CSP headers on some pages. Bundling avoids both problems.

activeTab is enough — the extension only needs activeTab, scripting, and storage permissions. No broad host permissions for the table-reading functionality. The only host permission is api.lemonsqueezy.com for license key activation. That keeps the permission prompt honest.

Nested tablesquerySelectorAll('table') catches nested tables too. I skip any <table> whose parent is inside another <table>. Without that filter, a table used for layout inside a data table shows up as a separate entry, which is confusing.

Virtualized tables are a real cliff — I initially thought I could handle them with a scroll-and-capture approach. The DOM truly does not contain the full dataset in those cases; the rows are created and destroyed as you scroll. Documenting the limitation honestly turned out to be the right call rather than shipping a partial solution.


Try it

Chrome Web Store listing — seven-day trial, no account.

Questions: support@hudsonenterprisesllc.com


I built this. Hudson Enterprises LLC is an Indiana software studio.

Top comments (0)