Skip to content

Instantly share code, notes, and snippets.

@the-code-rider
Created December 22, 2025 11:04
Show Gist options
  • Select an option

  • Save the-code-rider/96838f5d6ff538377776b6ddbb1c633d to your computer and use it in GitHub Desktop.

Select an option

Save the-code-rider/96838f5d6ff538377776b6ddbb1c633d to your computer and use it in GitHub Desktop.
scrapes spotify's top 10k song as csv from this page https://annas-archive.li/blog/spotify/spotify-top-10k-songs-table.html
(() => {
// 1) Find the biggest table on the page (handles cases with multiple tables)
const tables = [...document.querySelectorAll("table")];
if (!tables.length) throw new Error("No <table> elements found.");
const table = tables
.map(t => ({ t, rows: t.querySelectorAll("tbody tr").length }))
.sort((a, b) => b.rows - a.rows)[0].t;
// 2) Extract header
const headerCells =
[...table.querySelectorAll("thead tr th")].map(th => th.innerText.trim()) ||
[];
// Fallback if <thead> is missing
const firstRowCells = [...(table.querySelector("tbody tr")?.children ?? [])].map(
td => td.innerText.trim()
);
const headers = headerCells.length ? headerCells : firstRowCells.map((_, i) => `col_${i+1}`);
// 3) Extract body rows
const rows = [...table.querySelectorAll("tbody tr")].map(tr =>
[...tr.children].map(td => td.innerText.replace(/\s+/g, " ").trim())
);
// 4) CSV encode
const esc = (v) => {
const s = (v ?? "").toString();
return /[",\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
};
const csv = [
headers.map(esc).join(","),
...rows.map(r => r.map(esc).join(",")),
].join("\n");
// 5) Download
const blob = new Blob([csv], { type: "text/csv;charset=utf-8" });
const a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = "spotify-top-10k-songs-table.csv";
document.body.appendChild(a);
a.click();
a.remove();
return `Exported ${rows.length} rows to spotify-top-10k-songs-table.csv`;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment