Scrape the Spotify web player
Sometimes you just need the song info off a page, the track names, the artists, the albums, the release dates sitting in a playlist or a discography. A bot can read it straight off the Spotify web player and drop it in a sheet, with no copying by hand. There are three ways to start, with no code, with code, or with a Claude skill.
What I mean by scraping the Spotify web player
Scraping the Spotify web player means a bot reads the song information shown on the page and pulls it into a sheet. The tracks in a playlist, the albums in an artist's discography, the results of a search, the details you can see but do not want to copy by hand. It reads what the web player renders, row by row, and hands you clean data to work with.
The API is genuinely good here
Be honest about the easy path first. Spotify has a proper Web API, well documented and free for metadata, and for clean track, artist, and playlist data it is the right tool. If you are pulling a lot of structured song info, learn the API.
The browser route is for the gaps. When you do not want to set up credentials for a one-off pull. When you need exactly what the web player shows, a view the API does not expose. Or when a quick scrape into a sheet beats writing code against an endpoint. Same song info, a different door, useful when the API is more setup than the job is worth.
Who this is for
This is for anyone who wants song data without the developer setup. A music writer pulling a playlist into a spreadsheet, a researcher gathering release dates and credits, someone cataloguing an artist's full discography. You can read code or not, it does not matter here. No-coders and coders both, since you can build it without code and drop into code when you want.
How I'd approach it
Check the API first, because for plain metadata it is usually cleaner. If it does not fit, drive the web player. The discography pattern is a good shape to copy, read a list of artist links from a sheet, visit each one's discography, scrape the albums, and write them to a second sheet. Delete each artist row once it is done, so a stop and restart picks up where it left off instead of repeating.
API if it fits, the page if it does not, and clear the queue as you go. I would lay out the first draft with Build with description.
Scrape the Spotify web player from a description
Describe what you want in plain words in the Chrome extension and it builds the steps for you. There is a full walkthrough in the Spotify discography scraper guide, with a template you can install, and the example below follows it. To run it on a schedule, add a login step so it can sign in unattended. Explore no-code.
To the right is an example, the discography scraper from the guide. Describe your version and the AI lays out the steps.
Chrome extensionInstructions
- Read the artist links from a Google Sheet41 / 500
- Go to each artist's discography page36 / 500
- Scrape the album links22 / 500
- Open each album and scrape the title, copyright, and release date65 / 500
- Write the rows to a second Google Sheet, then delete the artist row67 / 500
Scrape the Spotify web player in code
Build with code. If you would rather script it yourself, this is the path. Explore code
Connect Playwright (or Puppeteer) to our cloud Chromium and write the same scripts you'd run locally, without managing the browser.
Code toolimport { chromium } from "playwright";
const browser = await chromium.connectOverCDP(
`wss://cdp-lb.axiom.ai/?token=${process.env.AXIOM_API_KEY}`
);
try {
const context = browser.contexts()[0];
const page = context.pages()[0] ?? await context.newPage();
// Artist links would come from your Google Sheet
const artists = ["https://open.spotify.com/artist/<id>"];
const data = [];
for (const artist of artists) {
// The discography view lives at /discography/all
await page.goto(`${artist}/discography/all`);
await page.waitForSelector("a[href*='/album/']");
const albumLinks = await page.$$eval("a[href*='/album/']", els =>
[...new Set(els.map(a => a.href))]
);
for (const link of albumLinks) {
await page.goto(link);
data.push({
title: await page.locator("h1").innerText(),
release: await page.locator("[data-testid='release-date']").innerText(),
copyright: await page.locator("[data-testid='copyright']").innerText(),
});
}
}
console.log(data); // write these to your second sheet
} finally {
await browser.close();
}
Build with a Claude skill
Build no-code or code bots with a skill.
Add the Claude skill and describe the song data you want. It builds the bot for you, no-code or code, reading the web player into a sheet.

What can you scrape?
Most of what the web player shows. A couple of cases worth knowing first.
Works well
- Track, artist, and album names
- A whole discography into a sheet
- Album release dates and copyright
- Playlist and search results
- A list of artists from a sheet
Harder
- Audio features the API exposes but the page does not
- Very large catalogues in one run
- Content behind your login
Don't try
- Downloading audio or ripping tracks
- High-volume scraping against the terms
- Reselling Spotify's data
What I'd watch out for
The web player is a polished, lazy-loading app, so a few things trip up a scraper. Here is what I would watch for.
Try the API first
Spotify's Web API gives clean metadata without scraping. For structured track and album data it is usually less work than driving the page. Reach for the browser when the API does not cover what you need, or the setup is not worth it.
Delete as you go
Process an artist, then remove that row from the source sheet. If the bot stops and starts again, it picks up the unfinished rows instead of scraping the same artist twice. It is the difference between a queue and a loop that repeats.
Let the page load
The web player fills in as you scroll, and the discography view loads albums lazily. Wait for the rows to appear, and scroll if you need more, before you scrape, or you will catch a half-loaded page.
Respect the terms
Spotify's terms restrict scraping, so keep it to reasonable, low-volume pulls for your own use, and lean on the official API for anything heavier. Do not hammer the player.