# Spotify Metadata Scraper (`fascinating_lentil/spotify-metadata-scraper`) Actor

Extract public metadata and nested track lists from Spotify URLs without login or an API key.

- **URL**: https://apify.com/fascinating\_lentil/spotify-metadata-scraper.md
- **Developed by:** [Md Jakaria Mirza](https://apify.com/fascinating_lentil) (community)
- **Categories:** Automation, Developer tools, Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 spotify items

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Spotify Scraper - Tracks, Artists, Albums, Playlists & Podcasts Metadata

Scrape public **Spotify metadata** from tracks, artists, albums, playlists, podcast shows, and episodes. This Spotify scraper extracts names, artists, authors, release dates, durations, cover images, preview URLs, and playability from any Spotify web URL or `spotify:` URI. Export to JSON, CSV, Excel, or HTML, or pull via the Apify API — no Spotify login and no API key required, because it reads Spotify's public embed data.

Built with Node.js 20, TypeScript, and the Apify SDK. It accepts both web URLs and URIs, nests album tracks, artist top tracks, and up to 50 playlist tracks inside the parent record, retries temporary blocks, and supports optional Apify Proxy routing.

### What It Extracts

- `sourceUrl` — the input URL you provided
- `url` — canonical Spotify web URL
- `spotifyUri` — the `spotify:` URI
- `type` — requested type (track, artist, album, playlist, show, episode)
- `resolvedType` — the type actually resolved from the page
- `id` — Spotify ID
- `name` — track, artist, album, playlist, show, or episode name
- `subtitle` — secondary line (e.g. artist or show context)
- `artists` — list of artists with `name`, `uri`, `url`
- `authors` — list of authors/publishers (podcasts) with `name`, `uri`, `url`
- `releaseDate` — release or publish date
- `durationMs` and `durationText` — duration in ms and human-readable form
- `explicit` — explicit content flag
- `playable` and `playabilityReason` — playability status and reason
- `previewUrl` — audio preview URL
- `imageUrl` — primary cover image
- `images` — all cover images with `url`, `width`, `height`
- `trackCount` — number of nested tracks
- `tracksMayBePartial` — true when the embed track limit was reached
- `tracks` — nested track list (position, type, id, uri, url, name, subtitle, duration, explicit, playable, previewUrl)
- `featuredItem` — featured episode when a show resolves to one
- `scrapedAt` — extraction timestamp

### Use Cases

1. **Music catalog audits** — bulk-resolve Spotify URLs to clean metadata for cleanup and deduplication of internal datasets.
2. **Playlist research and curation** — pull playlist tracks, durations, and explicit flags to study or rebuild playlists.
3. **Artist top-track monitoring** — track an artist's top tracks and cover art over time.
4. **Podcast and episode indexing** — extract show and episode names, authors, dates, and preview links for podcast directories.
5. **Cover-art and preview-link collection** — gather high-resolution images and audio previews for enrichment or display.

### Pricing

This Actor uses Apify Pay Per Event pricing. You pay only for input items successfully saved to the dataset — nested tracks are included at no extra charge and failed inputs are not billed.

| Event name | Price per event | 1,000 items | 10,000 items |
| --- | ---: | ---: | ---: |
| `spotify-item` | $0.0015 | $1.50 | $15.00 |

### Input

| Field | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `startUrls` | array | yes | sample track | Spotify web URLs or `spotify:` URIs, one per line. |
| `maxItems` | integer | no | `100` | Maximum number of unique Spotify URLs to process (1–10000). |
| `maxConcurrency` | integer | no | `5` | Spotify pages fetched in parallel (1–20). |
| `proxyConfiguration` | object | no | Proxy off | Optional Apify Proxy settings. The public embed usually works without a proxy. |

### Example Input

```json
{
  "startUrls": [
    "https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC",
    "spotify:album:4m2880jivSbbyEGAKfITCa"
  ],
  "maxItems": 2,
  "proxyConfiguration": { "useApifyProxy": false }
}
````

### How to Scrape Spotify (Step by Step)

1. Click **Try for free** / **Run**.
2. Paste Spotify URLs or `spotify:` URIs into `startUrls`, one per line.
3. Set `maxItems` (start small to test) and optionally `maxConcurrency`.
4. Leave proxy off, or enable Apify Proxy if you need it.
5. Run, then export the results as JSON, CSV, Excel, or HTML, or pull them via the Apify API.

### Sample Output

```json
{
  "sourceUrl": "https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC",
  "url": "https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC",
  "spotifyUri": "spotify:track:4uLU6hMCjMI75M1A2tKUQC",
  "type": "track",
  "resolvedType": "track",
  "id": "4uLU6hMCjMI75M1A2tKUQC",
  "name": "Never Gonna Give You Up",
  "subtitle": "Rick Astley",
  "artists": [
    {
      "name": "Rick Astley",
      "uri": "spotify:artist:0gxyHStUsqpMadRV0Di1Qt",
      "url": "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt"
    }
  ],
  "authors": [],
  "releaseDate": "1987-07-27",
  "durationMs": 213573,
  "durationText": "3:33",
  "explicit": false,
  "playable": true,
  "playabilityReason": null,
  "previewUrl": "https://p.scdn.co/mp3-preview/example",
  "imageUrl": "https://i.scdn.co/image/example",
  "images": [
    { "url": "https://i.scdn.co/image/example", "width": 640, "height": 640 }
  ],
  "trackCount": 0,
  "tracksMayBePartial": false,
  "tracks": [],
  "featuredItem": null,
  "scrapedAt": "2024-06-10T12:00:00.000Z"
}
```

### How It Works

1. Validates and parses each input into a canonical URL, ID, type, and embed URL.
2. Fetches Spotify's public embed data for the item (optionally through Apify Proxy).
3. Extracts and cleans fields, nesting album/artist/playlist tracks into the parent record.
4. Deduplicates inputs and writes invalid or failed inputs to the separate `failed-urls` dataset.
5. Charges `spotify-item` only after a successful record is saved, then writes it to the Apify Dataset.

### Known Limits

- Spotify playlist embeds currently expose up to 50 tracks. `tracksMayBePartial` is `true` when that limit is reached.
- Spotify show embeds can resolve to a featured episode. In that case the show stays the parent record and the resolved episode is stored in `featuredItem`.
- This Actor extracts public metadata only. It does not download full audio or bypass Spotify access controls, so some fields (like `previewUrl`) may be `null` when Spotify does not expose them.

### Legal and Ethical Use

This Actor reads only public Spotify embed metadata and uses no login or API key. You are responsible for complying with Spotify's terms, copyright, and local regulations wherever you use the data.

### Local development

```powershell
npm install
npm run build
New-Item -ItemType Directory -Force storage/key_value_stores/default
Copy-Item test_input.json storage/key_value_stores/default/INPUT.json
npm start
```

### License

Apache-2.0. See `LICENSE`.

# Actor input Schema

## `startUrls` (type: `array`):

Spotify web URLs or spotify: URIs, one per line.

## `maxItems` (type: `integer`):

Maximum number of unique Spotify URLs to process.

## `maxConcurrency` (type: `integer`):

Number of Spotify pages fetched in parallel.

## `proxyConfiguration` (type: `object`):

Optional proxy settings. The public embed endpoint usually works without a proxy.

## Actor input object example

```json
{
  "startUrls": [
    "https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC",
    "https://open.spotify.com/album/4m2880jivSbbyEGAKfITCa",
    "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"
  ],
  "maxItems": 100,
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# 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 = {
    "startUrls": [
        "https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC",
        "https://open.spotify.com/album/4m2880jivSbbyEGAKfITCa",
        "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("fascinating_lentil/spotify-metadata-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 = { "startUrls": [
        "https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC",
        "https://open.spotify.com/album/4m2880jivSbbyEGAKfITCa",
        "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M",
    ] }

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

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

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

```

## CLI example

```bash
echo '{
  "startUrls": [
    "https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC",
    "https://open.spotify.com/album/4m2880jivSbbyEGAKfITCa",
    "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"
  ]
}' |
apify call fascinating_lentil/spotify-metadata-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=fascinating_lentil/spotify-metadata-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Spotify Metadata Scraper",
        "description": "Extract public metadata and nested track lists from Spotify URLs without login or an API key.",
        "version": "1.0",
        "x-build-id": "LbsCjK06NIBAU1Vex"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/fascinating_lentil~spotify-metadata-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-fascinating_lentil-spotify-metadata-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/fascinating_lentil~spotify-metadata-scraper/runs": {
            "post": {
                "operationId": "runs-sync-fascinating_lentil-spotify-metadata-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/fascinating_lentil~spotify-metadata-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-fascinating_lentil-spotify-metadata-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "startUrls"
                ],
                "properties": {
                    "startUrls": {
                        "title": "Spotify URLs or URIs",
                        "type": "array",
                        "description": "Spotify web URLs or spotify: URIs, one per line.",
                        "default": [
                            "https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxItems": {
                        "title": "Maximum input items",
                        "minimum": 1,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Maximum number of unique Spotify URLs to process.",
                        "default": 100
                    },
                    "maxConcurrency": {
                        "title": "Maximum concurrency",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "Number of Spotify pages fetched in parallel.",
                        "default": 5
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Optional proxy settings. The public embed endpoint usually works without a proxy.",
                        "default": {
                            "useApifyProxy": false
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
