# Spotify Scraper - Tracks, Albums, Artists & Playlists (`logiover/spotify-scraper`) Actor

Unofficial Spotify API — no key, no login. Search tracks, albums, artists, playlists, shows & episodes; pull artist discographies, album & playlist tracks, and new releases. Export Spotify data (popularity, ISRC, followers, durations) to JSON, CSV or Excel.

- **URL**: https://apify.com/logiover/spotify-scraper.md
- **Developed by:** [Logiover](https://apify.com/logiover) (community)
- **Categories:** Videos, Developer tools
- **Features:** Limited permissions
- **Stats:** 17 total users, 5 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Spotify Scraper — Tracks, Albums, Artists & Playlists Data API (No API Key)

![Apify Actor](https://img.shields.io/badge/Apify-Actor-00A67E?logo=apify\&logoColor=white) ![No API key](https://img.shields.io/badge/No%20API%20key-required-2ea44f) ![Pay per result](https://img.shields.io/badge/Pricing-Pay%20per%20result-1C7ED6) ![Category](https://img.shields.io/badge/Category-Music%20%2F%20Media-8B5CF6) ![Export](https://img.shields.io/badge/Export-JSON%20%7C%20CSV%20%7C%20Excel-F59E0B)

An **unofficial Spotify scraper** and structured **Spotify data API** in a single Apify Actor. Search tracks, albums, artists, playlists, podcast shows and episodes; pull an artist's full discography and top tracks; grab every track in an album or playlist; and browse new releases — all powered by **Spotify's own Web Player API** (the private GraphQL backend that open.spotify.com itself calls). There is **no Spotify API key to register, no login, no OAuth, and no cookie** to paste: the Actor reproduces the Web Player's anonymous handshake internally, then reads public catalog data and returns clean, flat JSON you can export to **CSV, Excel or JSON**. **Eight modes share one input form**, and every result is tagged with `_mode` and `type` so you can mix modes in a single dataset and filter later.

> ### 🏆 Why this Spotify scraper?
>
> **8 modes in 1 Actor** (search, artist, album, playlist, new releases, plus track/album/artist batch) · powered by Spotify's own Web Player GraphQL · **up to ~1,000 results per search type** and **thousands of tracks per playlist** · play counts, follower counts, monthly listeners, world rank, durations and explicit flags on every relevant row · export to JSON / CSV / Excel. The practical **Spotify Web API alternative** and **Spotify data export** tool for music analytics, A\&R research, recommendation engines, ML datasets and AI agents — with **no API key** and **no login**.

***

### ✨ What this Actor does / Key features

- 🔍 **Search everything** — search **tracks, albums, artists, playlists, podcast shows and episodes** by any keyword (a song, an artist, a mood, a genre word like `pop`, `love`, `remix`, `hits`). Offset pagination reaches up to ~1,000 results **per type** in one run — search several types at once.
- 🎤 **Artist deep-dive** — pass an artist id or URL and get the **artist profile** (verified badge, followers, monthly listeners, world rank) plus the **full album discography** (paginated) and the **top tracks with play counts** in one shot.
- 💿 **Album tracklists** — album details (label, release date, copyrights, total tracks) and **every track** with track/disc numbers, durations and play counts.
- 🎧 **Playlist extraction** — playlist metadata (owner, description, followers, track count) and **all tracks**, paginated 100 at a time. Public editorial and user playlists can hold **hundreds to thousands** of tracks — huge volume.
- 🆕 **New releases** — browse newly released albums, paginated.
- 📦 **Batch lookups** — feed many track / album / artist ids or URLs at once and pull full objects via Spotify's bulk endpoints (auto-chunked to the API limits).
- 🔢 **Rich, typed fields** — numbers stored as **real numbers** (play counts, durations, follower counts, monthly listeners, world rank, track numbers), booleans as **booleans** (explicit, verified, playable, collaborative) — ready for analytics with zero cleanup.
- 🗂️ **6 pre-built dataset views** — Overview, Tracks, Albums, Artists, Playlists and Podcasts — slice the data with zero post-processing.
- ⚡ **Keyless & fast** — anonymous Web-Player token minted internally (TOTP handshake), residential proxy with fresh IP per request, automatic token refresh and rate-limit backoff. No browser, no OAuth, no key.

#### The 8 modes

| Mode | What it returns |
|---|---|
| `search` | Search tracks / albums / artists / playlists / shows / episodes (up to ~1,000 per type — highest volume) |
| `artist` | Artist details + full album discography (paginated) + top tracks |
| `album` | Album details + all tracks (paginated) |
| `playlist` | Playlist details + all tracks (paginated; hundreds–thousands) |
| `newReleases` | Newly released albums, paginated |
| `tracks` | Batch: full track objects by id/URL |
| `albums` | Batch: full album objects by id/URL |
| `artists` | Batch: full artist objects by id/URL |

### 👥 Who is it for?

- **Music data analysts & researchers** building catalogs of tracks, play counts and release trends.
- **A\&R, label and playlist-marketing teams** tracking releases, playlist placements and follower growth.
- **Recommendation-engine & ML engineers** who need bulk track, artist and audio-metadata datasets.
- **App & product developers** who want a **Spotify API without registering an app** or handling OAuth token refresh.
- **Journalists, data storytellers and AI-agent builders** wiring Spotify catalog data into dashboards, RAG or LLM tools.

### 💡 Use cases

- **Music trend analytics** — pull hundreds of tracks for a broad query or a big playlist with play counts and release dates, then chart what's rising in a BI tool.
- **Playlist intelligence** — extract every track from editorial or competitor playlists, see which artists dominate, and monitor follower counts over time.
- **Artist & discography monitoring** — snapshot an artist's full catalog, top tracks and follower count on a schedule to track growth and new drops.
- **Catalog enrichment** — match your own library to Spotify by artist and album, and enrich it with play counts, cover art, durations and canonical URLs.
- **Recommendation & ML datasets** — bulk-ingest tracks, artists, genres and audio metadata to train content-based or collaborative recommenders.
- **AI agents & RAG** — expose the Actor as a tool so an LLM can answer "what are the most popular new pop albums this month?" or embed track and playlist metadata.

### 🚀 Why use this Spotify Scraper?

- ✅ **No API key, no login** — an anonymous Web-Player token is generated inside the Actor; you never register a Spotify app or paste a cookie.
- ✅ **Clean, typed fields** per entity — play counts, followers, monthly listeners, world rank, durations, explicit flags, labels, copyrights, cover art and canonical URLs.
- ✅ **Real volume** — ~1,000 results per search type, full paginated discographies, and thousands of playlist tracks in a single run.
- ✅ **Dropdown-driven input** — pick a mode and search type(s) from menus; paste ids **or** full Spotify URLs (the Actor parses the id for you).
- ✅ **Export anywhere** — JSON, CSV, Excel, HTML, RSS or JSON Lines, plus the Apify API, Google Sheets, webhooks and no-code tools.
- ✅ **Pay per result** — you pay for the rows you extract, with a free tier to try it first.

### 📤 What data can you extract?

Results stream to the dataset; every item carries `_mode`, `type` and `scrapedAt`. Field sets vary by entity type:

#### Track fields

| Field | Type | Description |
|-------|------|-------------|
| `id` | string | Spotify track id |
| `name` | string | Track title |
| `artists` | array | `[{ id, name }]` for each credited artist |
| `artistNames` | string | Artist names joined with `, ` |
| `albumId` / `albumName` | string | Parent album id / name |
| `releaseDate` | string | Album release date (`YYYY-MM-DD`) when available |
| `imageUrl` | string | Album cover (largest) |
| `durationMs` | number | Track length in milliseconds |
| `durationText` | string | Human-readable length, e.g. `3:52` |
| `playcount` | number | Total play count (on album/playlist/top-track rows) |
| `explicit` | boolean | Explicit-content flag |
| `trackNumber` / `discNumber` | number | Position within the album (on album/playlist rows) |
| `playable` | boolean | Whether the track is currently playable |
| `spotifyUrl` / `uri` | string | Canonical Spotify URL / URI |

> Note on richness: **search** results are the lightweight cards Spotify serves for a query (id, name, artists, album, duration, explicit). **Album, playlist and artist-top-track** rows are richer and add `playcount` and `trackNumber`. Use `album` / `playlist` / `artist` modes when you need the deepest per-track detail.

#### Artist fields

| Field | Type | Description |
|-------|------|-------------|
| `id` / `name` | string | Artist id / name |
| `verified` | boolean | Verified-artist badge |
| `followers` | number | Follower count (in `artist` / `artists` modes) |
| `monthlyListeners` | number | Monthly listeners (in `artist` / `artists` modes) |
| `worldRank` | number | Global artist rank (in `artist` / `artists` modes) |
| `biography` | string | Artist bio text when present |
| `imageUrl` | string | Artist photo (largest) |
| `spotifyUrl` / `uri` | string | Canonical Spotify URL / URI |

#### Album fields

`id`, `name`, `albumType` (album/single/compilation), `artists[]`, `artistNames`, `totalTracks` (number), `releaseDate`, `releaseDatePrecision`, `label`, `copyrights[]`, `imageUrl`, `spotifyUrl`, `uri`.

#### Playlist fields

`id`, `name`, `ownerName`, `description`, `followers` (number), `tracksTotal` (number), `collaborative` (boolean), `imageUrl`, `spotifyUrl`, `uri`.

#### Podcast (show / episode) fields

Shows: `id`, `name`, `publisher`, `description`, `totalEpisodes` (number), `explicit` (boolean), `imageUrl`, `spotifyUrl`. Episodes: `id`, `name`, `showName`, `description`, `durationMs` (number), `durationText`, `explicit` (boolean), `imageUrl`, `spotifyUrl`.

#### Real output example (track, from `playlist`)

```json
{
  "_mode": "playlist",
  "type": "track",
  "playlistId": "37i9dQZF1DXcBWIGoYBM5M",
  "playlistName": "Today's Top Hits",
  "subType": "track",
  "id": "0kosUz0jePvjiz4ctmR6wL",
  "name": "Dai Dai",
  "artists": [
    { "id": "0EmeFodog0BfCgMzAIvKQp", "name": "Shakira" },
    { "id": "3wcj11K77LjEY1PkEazffa", "name": "Burna Boy" }
  ],
  "artistNames": "Shakira, Burna Boy",
  "albumId": "1xUppB6E6dNzqTUj42Vgje",
  "albumName": "Dai Dai",
  "releaseDate": "2026-05-29",
  "imageUrl": "https://i.scdn.co/image/ab67616d0000b273...",
  "durationMs": 223448,
  "durationText": "3:43",
  "playcount": 221230434,
  "explicit": false,
  "trackNumber": 1,
  "discNumber": 1,
  "playable": true,
  "addedAt": "2026-05-29T04:02:20.322Z",
  "spotifyUrl": "https://open.spotify.com/track/0kosUz0jePvjiz4ctmR6wL",
  "uri": "spotify:track:0kosUz0jePvjiz4ctmR6wL",
  "scrapedAt": "2026-07-23T10:00:00.000Z"
}
```

### 🧭 How to use

#### Option A — search by keyword (build a big dataset)

1. Set **Mode** to `search`.
2. Type a **query** (`top hits`, `love`, `pop`, an artist name…) and pick a **search type** (Tracks by default). Add extra types to pull several at once. Broad single words return the most rows.
3. Set **Max results** (e.g. `600`) and run. The Actor paginates each type up to ~1,000 and exports the rows.

```json
{
  "mode": "search",
  "query": "top hits",
  "searchType": "track",
  "maxResults": 600
}
```

#### Option B — target an artist, album or playlist (by id or URL)

1. Set **Mode** to `artist`, `album` or `playlist`.
2. Paste an id **or** a full Spotify link — e.g. `https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M`. The Actor extracts the id automatically.
3. Run — you get the entity's details plus its tracks / discography, paginated up to **Max results**.

```json
{
  "mode": "playlist",
  "playlistId": "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M",
  "maxResults": 1000
}
```

### 📥 Input parameters

Pick a `mode`, then fill only the fields that mode needs. **Nothing is required** — empty input `{}` returns popular tracks (default query `top hits`).

| Field | Type | Used by | Description |
|-------|------|---------|-------------|
| `mode` | string (select) | all | `search`, `artist`, `album`, `playlist`, `newReleases`, `tracks`, `albums`, `artists`. |
| `query` | string | search | Free-text term (song, artist, mood, genre word). Broad terms return more. |
| `searchType` | string (select) | search | Primary type: track / album / artist / playlist / show / episode. |
| `searchTypes` | array (select) | search | Extra types to search at once. |
| `artistId` / `artistIds` | string / array | artist, artists | Artist id, URI or URL (batch supported). |
| `albumGroups` | array (select) | artist | Which album groups to include (album / single / compilation / appears_on). |
| `albumId` / `albumIds` | string / array | album, albums | Album id, URI or URL (batch supported). |
| `playlistId` / `playlistIds` | string / array | playlist | Playlist id, URI or URL (batch supported). |
| `trackId` / `trackIds` | string / array | tracks | Track id, URI or URL (batch supported). |
| `maxResults` | integer | all | Row cap per entity/target; drives pagination. Default 200. |
| `proxy` | object | all | Proxy config. Residential by default so Spotify doesn't rate-limit a shared IP. |

#### Full input JSON (artist deep-dive)

```json
{
  "mode": "artist",
  "artistId": "https://open.spotify.com/artist/3TVXtAsR1Inumwj472S9r4",
  "albumGroups": ["album", "single"],
  "maxResults": 500
}
```

### 📦 Output example (artist profile, from `artist`)

```json
{
  "_mode": "artist",
  "type": "artist",
  "artistId": "3TVXtAsR1Inumwj472S9r4",
  "subType": "artistDetails",
  "id": "3TVXtAsR1Inumwj472S9r4",
  "name": "Drake",
  "verified": true,
  "followers": 114316190,
  "monthlyListeners": 91531220,
  "worldRank": 12,
  "imageUrl": "https://i.scdn.co/image/ab6761610000e5eb...",
  "spotifyUrl": "https://open.spotify.com/artist/3TVXtAsR1Inumwj472S9r4",
  "uri": "spotify:artist:3TVXtAsR1Inumwj472S9r4",
  "scrapedAt": "2026-07-23T10:00:00.000Z"
}
```

### 💡 Tips for best results

- **Broaden the query for volume.** A single broad word (`love`, `pop`, `hits`, `remix`, `2024`, or an artist's name) returns far more tracks than a narrow multi-word phrase — set `maxResults` to 500–1,000 to fill a dataset fast.
- **Search several types at once.** Add `searchTypes: ["track","album","artist"]` to build a mixed catalog in one run; filter later on the `type` column.
- **Spotify caps search offset near 1,000.** To go deeper, run several related queries and merge the datasets.
- **Playlists are the volume champion.** Editorial playlists (e.g. Today's Top Hits) and large user playlists return hundreds to thousands of tracks — perfect for big pulls.
- **Paste URLs, not just ids.** Any `open.spotify.com/...` link or `spotify:...:...` URI works; the Actor extracts the id.
- **Use detail modes for the richest tracks.** `album`, `playlist` and `artist` (top tracks) rows include `playcount` and `trackNumber`; plain search rows are lighter.
- **Artist stats are gold.** `artist` mode returns `followers`, `monthlyListeners` and `worldRank` — great for tracking artist momentum over time.
- **Keep residential proxy on.** Spotify rate-limits shared IPs; the default residential proxy with per-request IP rotation keeps runs healthy.
- **Schedule snapshots.** Re-run daily/weekly to track play-count, follower and playlist changes over time.
- **Use the views.** Switch to the Tracks, Albums, Artists or Playlists view for a tidy, typed table with zero post-processing.

### 🔌 Integrations

Schedule this Actor on Apify to refresh a music dataset daily or weekly. Export results to **JSON, CSV or Excel**, sync to **Google Sheets**, push to your database or BI tool, or fan out via **webhooks**. Connect it to **Make, n8n and Zapier**, or call it from your stack with `run-sync-get-dataset-items` and the JavaScript / Python clients. Send new tracks to **Slack** or a data warehouse as they appear.

### 🔧 API usage

Run the Actor and fetch results over the Apify API. Get your token from the Apify Console.

**cURL**

```bash
curl -X POST "https://api.apify.com/v2/acts/logiover~spotify-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"mode":"search","query":"top hits","searchType":"track","maxResults":600}'
```

**Node.js**

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('logiover/spotify-scraper').call({
  mode: 'playlist',
  playlistId: 'https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M',
  maxResults: 1000,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

**Python**

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_TOKEN")
run = client.actor("logiover/spotify-scraper").call(run_input={
    "mode": "artist",
    "artistId": "https://open.spotify.com/artist/3TVXtAsR1Inumwj472S9r4",
    "maxResults": 500,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["name"], item.get("followers"))
```

### 🤖 Use with AI agents (MCP)

Because this Actor is keyless and returns clean JSON, it plugs straight into LLM tool-calling and the Apify MCP server. Expose it as a tool and let an agent answer catalog questions on demand — e.g. prompt: *"Use the Spotify scraper to list 50 tracks for the query 'top hits' and summarize the most common artists."* The agent sends `{"mode":"search","query":"top hits","searchType":"track","maxResults":50}` and reasons over the structured rows.

### ❓ Frequently Asked Questions

#### Do I need a Spotify API key or account?

No. This is an unofficial Spotify scraper that reads publicly available catalog data through Spotify's own Web Player backend. The Actor reproduces the Web Player's anonymous handshake internally, so you never register a Spotify developer app, handle OAuth, or paste a cookie. You only need an Apify account.

#### Is this a Spotify API or a Spotify API alternative?

Both, effectively. It works as an unofficial **Spotify API** and a practical **Spotify Web API alternative**: send structured input, get structured JSON back, without registering an app, managing client credentials, or refreshing OAuth tokens yourself.

#### How do I scrape Spotify track data like play counts and durations?

Use `album`, `playlist` or `artist` (top tracks) mode for the richest rows — each track includes `playcount`, `durationMs`, `explicit`, `trackNumber`, and the album/artist context. The `search` mode returns lighter track cards (id, name, artists, album, duration, explicit) ideal for high-volume discovery.

#### How many results can one run return?

Search paginates up to ~1,000 results **per type** (Spotify's offset limit), and you can search several types at once. Playlists return **all** their tracks (often hundreds to thousands), and artist mode returns the full discography plus top tracks. A single run routinely yields hundreds to thousands of rows.

#### Can I scrape an entire playlist's tracks?

Yes. Pick `playlist` mode and paste the playlist id or `open.spotify.com/playlist/...` URL. The Actor pulls playlist metadata plus every track, paginated 100 at a time, up to your `maxResults`.

#### Can I paste Spotify URLs instead of ids?

Yes. Any bare id, `spotify:track:…` / `spotify:artist:…` URI, or `open.spotify.com/...` URL (including `/intl-xx/` localized links) is accepted — the Actor extracts the id automatically.

#### How do I export Spotify data to CSV, JSON or Excel?

Run any mode and download the dataset as CSV, JSON, Excel (XLSX), HTML, RSS or JSON Lines from the run page, or pull it via the Apify API. This makes it a simple **Spotify data export** and music-dataset tool.

#### Why is a residential proxy used by default?

Spotify rate-limits shared datacenter IPs quickly. The Actor uses Apify residential proxy with a fresh IP per request and automatic 429 backoff so large runs stay healthy. You can override the proxy in the input.

#### Does it cover podcasts?

Yes. Search with type `show` or `episode` to pull podcast shows (publisher, total episodes) and episodes (duration, explicit flag) alongside music.

#### What if a search returns few results or some fields are null?

Narrow multi-word phrases return fewer rows than broad single words — try `love`, `pop`, `hits`, or an artist name and raise `maxResults`. Some fields are only present on richer paths (e.g. `playcount`/`trackNumber` on album/playlist rows, `followers`/`monthlyListeners` on artist rows). Core fields (id, name, artists, URLs, duration) are always populated.

#### How often is the data updated?

Data is fetched live from Spotify at run time, so every run reflects the current catalog, play counts and follower counts. Schedule the Actor to capture changes over time.

#### Is it legal to scrape Spotify?

The Actor collects only publicly available catalog data served by Spotify's own endpoints, for legitimate research, analytics and dataset-building. You are responsible for using the data in compliance with Spotify's terms of service and applicable laws. It does not download audio or access any private/user data.

### ⚖️ Is it legal?

This Actor extracts only publicly available metadata served by Spotify's own public endpoints and is intended for legitimate research, analytics and dataset-building use. It does **not** download copyrighted audio and does **not** access private accounts or user data. You are responsible for complying with Spotify's Terms of Service and any applicable local laws and privacy regulations.

This Actor is an independent tool. It is not affiliated with, endorsed by, or sponsored by Spotify; Spotify and all other trademarks mentioned here are the property of their respective owners.

### 🔗 Related scrapers by logiover

Building a music, media or entertainment dataset? Pair Spotify with the rest of the suite:

| Actor | What it does |
|---|---|
| [Discogs Scraper](https://apify.com/logiover/discogs-scraper) | Music releases, artists and labels from Discogs |
| [Apple Podcasts Episode Scraper](https://apify.com/logiover/apple-podcasts-episode-scraper) | Podcast episodes and show metadata |
| [IMDb Scraper](https://apify.com/logiover/imdb-scraper) | Movies, TV, ratings, reviews and cast |
| [Twitch Scraper](https://apify.com/logiover/twitch-scraper) | Streams, channels and metadata from Twitch |

👉 Browse all **[logiover scrapers on Apify Store](https://apify.com/logiover)** — 180+ actors across media, social, real estate, jobs, crypto and B2B data.

### ⭐ Support & feedback

Found a bug or need an extra field or mode? Open an issue on the **Issues** tab — response is usually fast. If this Actor saves you time, a **★★★★★ review** on the Store page genuinely helps and is hugely appreciated. 🙏

***

### 📝 Changelog

#### 2026-11-01

- Monthly health check (2026-11-01): a live run on the current build completed successfully and returned data. Input options, output fields and pricing are unchanged.
- README refreshed: 1 link to retired Actors removed; independence disclaimer added.

#### 2026-10-15

- Every request now has a hard time limit, so a proxy connection that stalls can no longer hold up the run or push it past its timeout.
- A run that reaches its maximum cost per run now stops cleanly with its results saved and a status message, instead of ending as aborted.
- A proxy group your account cannot use no longer stops the run at start-up; it falls back to the default Apify Proxy.
- Runs with a short timeout (API and AI-agent calls) now finish inside it with what they collected, instead of being cut off.
- Memory is managed within the run's own limit, which removes a rare out-of-memory crash on large pages.
- The prefilled example for `maxResults` is now 400 (was 200).
- The default used when the field is left out for `maxResults` is now 11,320 (was 200).

#### 2026-09-23

- Fleet-wide quality audit. Verified end to end against live data and re-checked the input schema, the output columns and the run configuration.
- Output verified on a live run: 22 columns returned, 81.8% of cells populated.
- Run reliability reviewed: 100.0% of public runs succeeded in the last 30 days.
- Input schema, output schema and pricing configuration reviewed.
- Noted that 4 column(s) came back empty in this sample (`releaseDate`, `playcount`, `trackNumber`, `discNumber`); these are under review.

#### 2026-09-01

- Fleet-wide health check. Verified against this Actor's real run history: 30-day success rate, output row counts, per-field fill rates, and peak memory against the configured memory limit.
- Reviewed for the failure patterns that have cost this fleet runs — unguarded proxy setup, retry loops that can outlast the run's own time budget, and full-page HTML parsing that can exhaust a small container.
- No change to input, output fields or scraping logic.

#### 2026-08-11

- Maintenance release: refreshed the build and dependencies.
- Re-verified live execution, non-empty structured output and dataset field/type integrity.
- Reviewed reliability (retries, pagination) and output quality as part of a full-fleet QA pass.

#### 2026-08-01

- Completed the August 2026 full health check: verified empty/programmatic default, Console UI default, and two source-informed alternative inputs on Apify.
- Confirmed successful live execution, non-empty structured output, dataset-field/type integrity, and logical sample quality within the 5-minute quality window.
- Declared 22 dataset fields from typed live cloud samples so the output contract is no longer an empty placeholder.
- Declared 43 nullable dataset fields from typed live cloud samples so the output contract is no longer an empty placeholder or brittle to sparse modes.

#### 2026-07-23

- Initial release: eight Spotify modes (search, artist, album, playlist, new releases, plus track/album/artist batch) over Spotify's own Web Player GraphQL backend. Keyless anonymous handshake (TOTP token + client-token), residential proxy with per-request IP rotation, automatic token refresh, persisted-query self-healing and rate-limit backoff. Typed fields per entity (play counts, followers, monthly listeners, world rank, durations) and six pre-built dataset views.

***

\*Maintained: last verified 2026-11-01 — checked end-to-end against live run history (reliability, output fields and types, and time/memory budgets).

# Changelog

This Actor's version history is a separate document: https://apify.com/logiover/spotify-scraper/changelog.md

# Actor input Schema

## `mode` (type: `string`):

Which Spotify endpoint to run.

• **search** — search tracks / albums / artists / playlists / shows / episodes; paginates up to ~1,000 results per type (highest volume)
• **artist** — artist details + full album discography (paginated) + top tracks, by id or URL
• **album** — album details + all tracks (paginated), by id or URL
• **playlist** — playlist details + all tracks (paginated; public playlists have hundreds–thousands)
• **newReleases** — browse newly released albums (paginated)
• **tracks** — batch fetch full track objects by id/URL
• **albums** — batch fetch full album objects by id/URL
• **artists** — batch fetch full artist objects by id/URL

## `query` (type: `string`):

Free-text term for **search** mode (song, artist, album, keyword, genre word). Broad terms return the most rows — e.g. `top hits`, `love`, `pop`, `remix`, `2024`, an artist or a mood. Each type paginates up to ~1,000 results. Leave empty to default to `top hits`.

## `searchType` (type: `string`):

Primary entity type to search for in **search** mode.

## `searchTypes` (type: `array`):

Search several entity types at once in **search** mode. Each type paginates independently up to `maxResults`.

## `artistId` (type: `string`):

Spotify artist id, `spotify:artist:…` URI, or `open.spotify.com/artist/…` URL. Used by **artist** mode (and **artists** batch).

## `artistIds` (type: `array`):

List of Spotify artist ids/URIs/URLs for batch **artist** / **artists** lookups.

## `albumGroups` (type: `array`):

Which album groups to include when pulling an artist's discography.

## `albumId` (type: `string`):

Spotify album id, `spotify:album:…` URI, or `open.spotify.com/album/…` URL. Used by **album** mode (and **albums** batch).

## `albumIds` (type: `array`):

List of Spotify album ids/URIs/URLs for batch **album** / **albums** lookups.

## `playlistId` (type: `string`):

Spotify playlist id, `spotify:playlist:…` URI, or `open.spotify.com/playlist/…` URL. Used by **playlist** mode.

## `playlistIds` (type: `array`):

List of Spotify playlist ids/URIs/URLs for batch **playlist** lookups.

## `trackId` (type: `string`):

Spotify track id, `spotify:track:…` URI, or `open.spotify.com/track/…` URL. Used by **tracks** batch mode.

## `trackIds` (type: `array`):

List of Spotify track ids/URIs/URLs for batch **tracks** lookups (up to 50 per API call, auto-chunked).

## `maxResults` (type: `integer`):

Upper bound on rows per entity/target. For search this caps each type at ~1,000 (Spotify's offset limit); for artist/album/playlist it drives pagination. Empty input uses 200.

## `proxy` (type: `object`):

Proxy used to reach Spotify. Residential is recommended (and default) so Spotify does not rate-limit a shared datacenter IP. A fresh IP is used per request.

## Actor input object example

```json
{
  "mode": "search",
  "query": "top hits",
  "searchType": "track",
  "searchTypes": [],
  "artistId": "https://open.spotify.com/artist/3TVXtAsR1Inumwj472S9r4",
  "artistIds": [],
  "albumGroups": [
    "album",
    "single"
  ],
  "albumId": "https://open.spotify.com/album/4aawyAB9vmqN3uQ7FjRGTy",
  "albumIds": [],
  "playlistId": "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M",
  "playlistIds": [],
  "trackId": "https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b",
  "trackIds": [],
  "maxResults": 400,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Full results dataset. Use the Tracks view for track rows, Albums for albums, Artists for artist profiles, and Playlists for playlist metadata.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "mode": "search",
    "query": "top hits",
    "searchType": "track",
    "albumGroups": [
        "album",
        "single"
    ],
    "maxResults": 400,
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("logiover/spotify-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "mode": "search",
    "query": "top hits",
    "searchType": "track",
    "albumGroups": [
        "album",
        "single",
    ],
    "maxResults": 400,
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("logiover/spotify-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "mode": "search",
  "query": "top hits",
  "searchType": "track",
  "albumGroups": [
    "album",
    "single"
  ],
  "maxResults": 400,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call logiover/spotify-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,logiover/spotify-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/IQwTuqbTN2RKQ28z6/builds/Obz4CgeefsapNJB3c/openapi.json
