JavaScript Bookmarklet to Extract Table Data into CSV
Have you ever landed on a website with a useful HTML table but no option to export the data? With this tutorial, you’ll learn how to create a reusable JavaScript bookmarklet that scrapes any table on a webpage and downloads the data as a clean CSV file — no manual copying or external tools required.
1. What Is a Bookmarklet and Why Use One?
A bookmarklet is a small JavaScript script stored as a URL in a browser bookmark. When clicked, the script runs in the context of the current page. This is incredibly useful for quick browser-based tooling — like scraping data — without needing developer tools or plugins.
Use cases include:
- Exporting product lists from e-commerce sites
- Extracting pricing or inventory tables
- Saving sports stats, schedules, or reports with dynamic UIs
We’ll build a bookmarklet that locates all visible HTML tables, parses the data, and downloads each table as a CSV file — all with a single click.
2. Parsing HTML Tables into CSV Format
HTML tables are structured using <table>
, <tr>
, <th>
, and <td>
elements. To convert to CSV, we need to:
- Get rows and columns from each table
- Clean cell content (e.g., remove commas, newlines)
- Build CSV strings with appropriate delimiters
Here’s a function that takes a table element and returns a CSV string:
function tableToCSV(table) {
const rows = Array.from(table.querySelectorAll("tr"));
return rows.map(row => {
const cells = Array.from(row.querySelectorAll("th,td"));
return cells.map(cell => {
let text = cell.innerText.trim();
text = text.replace(/"/g, '""'); // Escape quotes
return `"${text}"`;
}).join(",");
}).join("\n");
}
This handles both headers and data cells and escapes quotes for proper CSV formatting.
3. Automating CSV Download in the Browser
Once we generate CSV data, we want to trigger a download. We’ll use a blob and an anchor tag to do this dynamically:
function downloadCSV(csvData, filename="table.csv") {
const blob = new Blob([csvData], { type: "text/csv;charset=utf-8;" });
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = filename;
link.click();
}
This snippet creates a downloadable file without user permission dialogs, making the UX seamless.
4. Scanning All Tables on a Page
To cover multiple tables, we can iterate through every <table>
element on the page. We’ll download each as its own CSV file with a unique name:
function exportAllTables() {
const tables = document.querySelectorAll("table");
if (tables.length === 0) {
alert("No tables found on this page.");
return;
}
tables.forEach((table, index) => {
const csv = tableToCSV(table);
const filename = `table-${index + 1}.csv`;
downloadCSV(csv, filename);
});
}
This makes the bookmarklet flexible — whether there’s one table or many, it handles them all with consistent naming.
5. Packaging Into a Bookmarklet
To convert your script into a bookmarklet, wrap it into an IIFE (Immediately Invoked Function Expression), minify it, and prefix it with javascript:
. Here’s the full bookmarklet code:
javascript:(function(){
function tableToCSV(table){
const rows=Array.from(table.querySelectorAll("tr"));
return rows.map(row=>{
const cells=Array.from(row.querySelectorAll("th,td"));
return cells.map(cell=> {
let text=cell.innerText.trim().replace(/"/g,'""');
return `"${text}"`
}).join(",");
}).join("\n");
}
function downloadCSV(data,filename){
const blob=new Blob([data],{type:"text/csv;charset=utf-8;"}),
link=document.createElement("a");
link.href=URL.createObjectURL(blob);
link.download=filename;
link.click();
}
const tables=document.querySelectorAll("table");
if(!tables.length) return alert("No tables found.");
tables.forEach((t,i)=>{
const csv=tableToCSV(t);
downloadCSV(csv,`table-${i+1}.csv`);
});
})();
To use it:
- Create a new bookmark in your browser.
- Set the name to “Table2CSV” (or whatever you like).
- Paste the above code as the bookmark URL (remove newline characters first).
- Navigate to any page with a table and click your bookmark.
Bonus Tips & Best Practices
- If table content is rendered dynamically (JavaScript/DataTables), ensure all rows are loaded before running the bookmarklet.
- Prefer
textContent
overinnerText
if you want exact HTML text (faster but may include hidden elements). - To handle nested tables, update the selector logic with specificity.
- Consider adding filters to export only visible or selected tables.
Conclusion
This lightweight utility empowers you to grab structured data from any website — instantly and code-free. With under 3KB of JavaScript, the bookmarklet approach is an elegant, portable automation tool that’ll make your web scraping hassle-free. Keep it in your toolbox and never retype tabular data again!
Useful links: