# Spotify Play Count & Insights Scraper (`brilliant_gum/spotify-insights-scraper`) Actor

Exact stream counts, monthly listeners, world rank, full discography PLUS historical trend tracking, related artists, playlists, contact info (emails/socials), revenue estimates, lyrics and podcasts. Drop-in superset of beatanalytics/spotify-play-count-scraper.

- **URL**: https://apify.com/brilliant\_gum/spotify-insights-scraper.md
- **Developed by:** [Yuliia Kulakova](https://apify.com/brilliant_gum) (community)
- **Categories:** Developer tools, Social media, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 entity scrapeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 Play Count & Insights Scraper

Exact **stream counts**, **monthly listeners**, **world rank** and the **full discography graph** straight from Spotify — the data the official Web API hides — **plus** historical trend tracking, related artists, playlists, lead-gen contact info, lyrics and podcasts.

A **drop-in superset** of `beatanalytics/spotify-play-count-scraper`: the same inputs work unchanged, and it returns the same fields and many more.

![banner](https://i.imgur.com/hVgRiFG.png)

---

### What you get

| | |
|---|---|
| **Exact play counts** | Per-track stream counts that the Spotify Web API doesn't expose. |
| **Audience signals** | Monthly listeners, followers, world rank, top cities (with listener counts per city). |
| **Full discography** | Albums, singles, popular releases, "Appears On", "Featuring" — with per-track streams. |
| **Related artists graph** | "Fans also like" with optional enrichment (monthly listeners + followers per related artist) and graph-crawl depth. |
| **Playlist attribution** | "Discovered On" — which editorial/user playlists are driving the streams. |
| **Historical trends** | Persisted snapshots + automatic deltas + stream velocity per day across scheduled runs. |
| **Lead-gen contact info** | Emails (from bio) + categorised social links + website. |
| **Revenue estimates** | Per-artist royalty range from the industry-standard $0.003–0.005 per-stream payout band. |
| **Lyrics** | Time-synced lyrics per track (requires your `sp_dc` cookie — see FAQ). |
| **Podcasts** | Show metadata + paginated episode list (name, duration, release date). |
| **Full playlist contents** | Owner, follower count, paginated track list with `addedAt` timestamps. |
| **Original-actor compatibility** | Optional flat `play_counts.csv` export matching `beatanalytics/spotify-play-count-scraper`. |

Works without configuration — proxies are included, auth is self-healing, and the actor is resilient to Spotify's periodic web-player rotations.

---

### Use cases

- **Music marketer / A&R** — scout rising artists by city, by monthly-listener velocity, by playlist co-occurrence.
- **Independent label / Manager** — pull contact info and audience size for outreach targeting.
- **Music journalist / Analyst** — cite exact stream counts with provenance.
- **Royalty analyst** — estimate revenue from streams using transparent payout assumptions.
- **Playlist curator** — see which playlists already feature an artist.
- **Data engineer** — schedule the actor and feed a clean time-series into your warehouse.
- **Podcast aggregator** — pull show metadata + full episode catalogue.

---

### Quick start

Paste a Spotify URL — that's the whole minimum input:

```json
{
  "urls": ["https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02"]
}
````

You get an artist record with monthly listeners, followers, world rank, top 10 tracks (with stream counts), top 5 cities, full discography lists, biography, external links, contact info, and analytics — all in one record.

***

### Common inputs

**Crawl all albums of an artist (full per-track streams):**

```json
{
  "urls": ["https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02"],
  "followAlbums": true
}
```

**Scrape by keyword instead of URL:**

```json
{
  "searchQueries": ["Taylor Swift", "phonk", "lofi beats"],
  "searchType": "track",
  "maxSearchResults": 5
}
```

**Resolve a playlist fully (with follower count):**

```json
{
  "urls": ["https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"],
  "includePlaylists": true
}
```

**Related-artists graph with monthly-listener enrichment:**

```json
{
  "urls": ["https://open.spotify.com/artist/3TVXtAsR1Inumwj472S9r4"],
  "includeRelatedArtists": true,
  "relatedArtistsDepth": 1,
  "enrichRelatedArtists": true,
  "includeDiscoveredOnPlaylists": true
}
```

**Historical trend tracking — schedule daily/weekly:**

```json
{
  "urls": ["https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02"],
  "enableHistory": true,
  "historyDatasetName": "my-spotify-history"
}
```

From the second run onwards every record carries a `history.delta` block with `streamChange`, `listenerChange`, `streamVelocityPerDay`, and a `trend` (`up` / `down` / `flat`).

**Podcast show + episode catalogue:**

```json
{
  "urls": ["https://open.spotify.com/show/2MAi0BvDc6GTFvKFPXnkCL"],
  "includePodcasts": true
}
```

***

### Inputs reference

#### Compatible with `beatanalytics/spotify-play-count-scraper`

| Field | Type | Default | Description |
|---|---|---|---|
| `urls` | array | — | Spotify URLs/URIs (artist, album, track, playlist, show, episode) |
| `followAlbums` | boolean | false | For each artist URL, also crawl every album |
| `followSingles` | boolean | false | For each artist URL, also crawl every single/EP |
| `followPopularReleases` | boolean | false | Crawl Spotify's curated "popular releases" |
| `scrapePreviewUrls` | boolean | false | Include 30s preview URLs alongside play counts |

#### Added in this actor

| Field | Type | Default | Description |
|---|---|---|---|
| `searchQueries` | array | — | Scrape by keyword instead of URL |
| `searchType` | enum | `artist` | `artist` / `album` / `track` / `playlist` / `all` |
| `maxSearchResults` | int | 5 | Results per search query |
| `includeRelatedArtists` | boolean | false | Add "Fans also like" graph |
| `relatedArtistsDepth` | int | 0 | Crawl related artists as their own records (0–3) |
| `includeDiscoveredOnPlaylists` | boolean | false | Playlist attribution per artist |
| `includePlaylists` | boolean | false | Resolve full playlist contents + follower count |
| `includeLyrics` | boolean | false | Time-synced lyrics (needs `spDcCookie`) |
| `includePodcasts` | boolean | false | Resolve shows + episodes |
| `includeAnalytics` | boolean | **true** | Engagement, revenue range, momentum, concentration |
| `includeContactInfo` | boolean | **true** | Emails + categorized socials + website |
| `includeAppearsOn` | boolean | false | "Appears On" + "Featuring" discography |
| `includeConcerts` | boolean | false | Concerts (best-effort — see FAQ) |
| `enrichRelatedArtists` | boolean | false | Add monthly listeners + followers to each related artist |
| `writePlayCountsCsv` | boolean | false | Emit flat `play_counts.csv` to the key-value store |
| `enableHistory` | boolean | false | Persist snapshots + compute trends/velocity |
| `historyDatasetName` | string | `spotify-history` | Named store reused across scheduled runs |
| `spDcCookie` | string (secret) | — | `sp_dc` cookie for lyrics |
| `proxyConfiguration` | object | auto | Optional. Proxies are included automatically — leave empty unless overriding. |
| `maxConcurrency` | int | 4 | Parallel workers |
| `minDelayMs` | int | 350 | Throttle between requests |

***

### Output

Every record carries `type`, `id`, `url`, `name`, `scrapedAt`. Type-specific fields are layered on top.

**Artist record:** `verified`, `followers`, `monthlyListeners`, `worldRank`, `topCities[]`, `topTracks[]`, `albums[]`, `singles[]`, `popularReleases[]`, `relatedArtists[]`, `discoveredOnPlaylists[]`, `biography`, `externalLinks[]`, `totalTopTrackStreams`, `followerToListenerRatio`, `contactInfo`, `analytics`, `history` (when enabled).

**Album:** albumType, releaseDate, label, copyright, full `tracks[]` (each with `streamCount`), `totalAlbumStreams`.

**Track:** `streamCount`, duration, contentRating, trackNumber, album metadata, artists.

**Playlist:** owner, follower count, paginated `tracks[]` with `addedAt`.

**Show:** publisher, description, totalEpisodes, paginated `episodes[]` with name + duration + releaseDate.

#### Analytics block

```json
{
  "engagementRate": 1.56,
  "topTrackConcentration": 0.08,
  "topTrackStreams": 17637107878,
  "estimatedTopTrackRevenueUSD": { "low": 52911324, "high": 88185539, "currency": "USD" },
  "streamPayoutAssumption": { "low": 0.003, "high": 0.005, "currency": "USD" },
  "discoveryPlaylistCount": 11,
  "momentum": { "streamVelocityPerDay": 0, "trend": "flat" }
}
```

#### History block (with `enableHistory`)

```json
{
  "firstSeen": "2026-05-01T00:00:00Z",
  "snapshotCount": 12,
  "previous": { "at": "...", "monthlyListeners": 1000000, "totalStreams": 500000000 },
  "delta": {
    "daysElapsed": 1.0,
    "streamChange": 1250000,
    "streamVelocityPerDay": 1250000,
    "trend": "up"
  },
  "series": [ { "at": "...", "monthlyListeners": 0, "totalStreams": 0 } ]
}
```

***

### Pricing

Simple pay-per-event:

| Event | Cost |
|---|---|
| Actor start | $0.01 |
| Each scraped entity (artist / album / track / playlist / show / episode) | $0.02 |

**Example run costs:**

| What you scrape | Calculation | Cost |
|---|---|---|
| 1 artist with analytics + contact info | $0.01 + 1 × $0.02 | **$0.03** |
| 10 artists | $0.01 + 10 × $0.02 | **$0.21** |
| 100 artists daily (trend tracking) | $2.01 / run | **~$60 / month** |
| 500 tracks (bulk play-count audit) | $0.01 + 500 × $0.02 | **$10.01** |
| 5,000 entities (catalog sweep) | $0.01 + 5,000 × $0.02 | **$100.01** |

Compare: Chartmetric / Soundcharts start at $250–350/month per seat and don't expose per-track play counts at all.

***

### FAQ

**Does this work without configuration?**
Yes. Paste a URL and run.

**Why does lyrics require a cookie?**
Spotify gates the lyrics endpoint behind a logged-in session. To use lyrics, paste your `sp_dc` cookie value (F12 → Application → Cookies → `sp_dc` on `open.spotify.com`) into the input field. Without it, every other feature still works.

**Are concerts complete?**
No — Spotify gates most concert data behind a logged-in session. Anonymous runs often return an empty list or partial entries with only an id. Use `includeConcerts: true` only when you specifically need the best-effort data.

**Why no genres?**
Spotify removed the `genres` array from the artist endpoint in 2024. Nobody has it via this API surface anymore.

**Are the revenue estimates accurate?**
They're a range based on the publicly cited Spotify net payout band of $0.003–0.005 per stream. We never claim a precise number — we always report a range, and we surface the `streamPayoutAssumption` so you can recompute with your own band.

**Can I export to CSV / Excel?**
Yes. Apify automatically offers CSV, JSON, Excel, XML, and HTML export on every dataset. Additionally, `writePlayCountsCsv: true` writes a flat `play_counts.csv` to the key-value store matching the original scraper's shape.

**Will repeated runs over-charge me for the same entity?**
Each run is metered independently. If you re-scrape the same artist daily, that's one billable entity per run. The historical store deduplicates time-series points so trend data stays clean.

**What's the difference vs `beatanalytics/spotify-play-count-scraper`?**
Drop-in superset. Same inputs, same field names — plus related artists, "Discovered On" playlists, lyrics, podcasts, search by query, contact info, analytics block, historical trends, and "Appears On" / "Featuring".

***

### Legal

This actor scrapes only publicly available Spotify data. It is **not affiliated with, endorsed by, or sponsored by Spotify**. Use responsibly and respect Spotify's Terms of Service and applicable laws.

***

Maintained by **brilliant\_gum** on Apify.

# Actor input Schema

## `urls` (type: `array`):

Spotify URLs of artists, albums or tracks to scrape. Accepts open.spotify.com links and spotify: URIs. Leave empty if you use 'Search queries' instead.

## `followAlbums` (type: `boolean`):

For each artist URL, also crawl every full album and return per-track play counts.

## `followSingles` (type: `boolean`):

For each artist URL, also crawl every single / EP.

## `followPopularReleases` (type: `boolean`):

For each artist URL, also crawl Spotify's curated 'popular releases'.

## `scrapePreviewUrls` (type: `boolean`):

Include 30-second audio preview URLs for tracks (alongside, not instead of, play counts).

## `searchQueries` (type: `array`):

NEW: scrape by keyword instead of URL. Each query is searched on Spotify and the top results are scraped. Pair with 'Search type' and 'Max search results'.

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

Which entity type to return for 'Search queries'.

## `maxSearchResults` (type: `integer`):

How many top results to scrape per search query.

## `includeRelatedArtists` (type: `boolean`):

NEW: add the related-artists graph to each artist record. Solves the #1 missing-field complaint.

## `relatedArtistsDepth` (type: `integer`):

0 = only list related artists on the record. 1+ = also scrape those related artists as their own records (graph crawl). Use with care, expands runs quickly.

## `includeDiscoveredOnPlaylists` (type: `boolean`):

NEW: which editorial/user playlists are driving an artist's streams (playlist attribution).

## `includePlaylists` (type: `boolean`):

NEW: for playlist URLs / search results, return full track listing, owner, and follower count (paginated past 100 tracks).

## `includeLyrics` (type: `boolean`):

NEW: time-synced lyrics per track (requires a valid 'sp\_dc cookie').

## `includePodcasts` (type: `boolean`):

NEW: resolve show & episode URLs (show metadata + episode list, episode metadata).

## `includeAnalytics` (type: `boolean`):

BONUS: per-artist analytics — engagement/loyalty rate, top-track concentration, estimated royalty revenue range, discovery reach, and momentum (from history). Turns raw numbers into decisions.

## `includeContactInfo` (type: `boolean`):

BONUS: emails (from bio) + categorized social links (Instagram/TikTok/YouTube/…) + website. Solves the marketer 'who do I contact' pain that competitors sell separately.

## `includeAppearsOn` (type: `boolean`):

BONUS: releases the artist appears on and playlists/releases featuring them — fuller discography graph.

## `includeConcerts` (type: `boolean`):

BONUS: upcoming concerts (venue, city, date). Note: Spotify gates most concert data behind a logged-in session, so anonymous runs often return an empty list.

## `enrichRelatedArtists` (type: `boolean`):

BONUS: fetch monthly listeners + rank for each related artist (adds one request per related artist).

## `writePlayCountsCsv` (type: `boolean`):

BONUS/compat: also emit a flat play\_counts.csv (artist\_url, artist\_name, album\_url, album\_name, track\_url, track\_name, play\_count) to the key-value store, matching the original actor.

## `enableHistory` (type: `boolean`):

THE killer feature: persist a timestamped snapshot every run into a named dataset, then compute deltas (daily stream change) and stream velocity vs the previous run. Run this actor on a schedule to build the time-series Spotify never gives you.

## `historyDatasetName` (type: `string`):

Named key-value store / dataset to persist snapshots into. Reused across scheduled runs to compute trends. Defaults to 'spotify-history'.

## `spDcCookie` (type: `string`):

Value of the 'sp\_dc' cookie from a logged-in open.spotify.com session. Only needed for lyrics. Stored as a secret.

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

Optional. Proxies are included and configured automatically — leave this empty unless you want to use your own.

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

Parallel request workers. Keep low (3-5) to avoid 429s.

## `minDelayMs` (type: `integer`):

Throttle to look human and avoid rate limits.

## Actor input object example

```json
{
  "urls": [
    "https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02",
    "https://open.spotify.com/album/1NAmidJlEaVgA3MpcPFYGq",
    "spotify:track:0VjIjW4GlUZAMYd2vXMi3b"
  ],
  "followAlbums": false,
  "followSingles": false,
  "followPopularReleases": false,
  "scrapePreviewUrls": false,
  "searchQueries": [
    "Taylor Swift",
    "phonk",
    "lofi beats"
  ],
  "searchType": "artist",
  "maxSearchResults": 5,
  "includeRelatedArtists": false,
  "relatedArtistsDepth": 0,
  "includeDiscoveredOnPlaylists": false,
  "includePlaylists": false,
  "includeLyrics": false,
  "includePodcasts": false,
  "includeAnalytics": true,
  "includeContactInfo": true,
  "includeAppearsOn": false,
  "includeConcerts": false,
  "enrichRelatedArtists": false,
  "writePlayCountsCsv": false,
  "enableHistory": false,
  "historyDatasetName": "spotify-history",
  "maxConcurrency": 4,
  "minDelayMs": 350
}
```

# Actor output Schema

## `summary` (type: `string`):

Counts of scraped entities and links to the persistent stores.

# 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 = {
    "urls": [
        "https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("brilliant_gum/spotify-insights-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 = { "urls": ["https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02"] }

# Run the Actor and wait for it to finish
run = client.actor("brilliant_gum/spotify-insights-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 '{
  "urls": [
    "https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02"
  ]
}' |
apify call brilliant_gum/spotify-insights-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Spotify Play Count & Insights Scraper",
        "description": "Exact stream counts, monthly listeners, world rank, full discography PLUS historical trend tracking, related artists, playlists, contact info (emails/socials), revenue estimates, lyrics and podcasts. Drop-in superset of beatanalytics/spotify-play-count-scraper.",
        "version": "1.0",
        "x-build-id": "bbwrXKhoTyjccX6al"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/brilliant_gum~spotify-insights-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-brilliant_gum-spotify-insights-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/brilliant_gum~spotify-insights-scraper/runs": {
            "post": {
                "operationId": "runs-sync-brilliant_gum-spotify-insights-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/brilliant_gum~spotify-insights-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-brilliant_gum-spotify-insights-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",
                "properties": {
                    "urls": {
                        "title": "Spotify URLs",
                        "type": "array",
                        "description": "Spotify URLs of artists, albums or tracks to scrape. Accepts open.spotify.com links and spotify: URIs. Leave empty if you use 'Search queries' instead.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "followAlbums": {
                        "title": "Follow albums",
                        "type": "boolean",
                        "description": "For each artist URL, also crawl every full album and return per-track play counts.",
                        "default": false
                    },
                    "followSingles": {
                        "title": "Follow singles",
                        "type": "boolean",
                        "description": "For each artist URL, also crawl every single / EP.",
                        "default": false
                    },
                    "followPopularReleases": {
                        "title": "Follow popular releases",
                        "type": "boolean",
                        "description": "For each artist URL, also crawl Spotify's curated 'popular releases'.",
                        "default": false
                    },
                    "scrapePreviewUrls": {
                        "title": "Scrape 30s preview URLs",
                        "type": "boolean",
                        "description": "Include 30-second audio preview URLs for tracks (alongside, not instead of, play counts).",
                        "default": false
                    },
                    "searchQueries": {
                        "title": "Search queries (no URL needed)",
                        "type": "array",
                        "description": "NEW: scrape by keyword instead of URL. Each query is searched on Spotify and the top results are scraped. Pair with 'Search type' and 'Max search results'.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "searchType": {
                        "title": "Search type",
                        "enum": [
                            "artist",
                            "album",
                            "track",
                            "playlist",
                            "all"
                        ],
                        "type": "string",
                        "description": "Which entity type to return for 'Search queries'.",
                        "default": "artist"
                    },
                    "maxSearchResults": {
                        "title": "Max results per search query",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "How many top results to scrape per search query.",
                        "default": 5
                    },
                    "includeRelatedArtists": {
                        "title": "Include related artists ('Fans also like')",
                        "type": "boolean",
                        "description": "NEW: add the related-artists graph to each artist record. Solves the #1 missing-field complaint.",
                        "default": false
                    },
                    "relatedArtistsDepth": {
                        "title": "Related-artists crawl depth",
                        "minimum": 0,
                        "maximum": 3,
                        "type": "integer",
                        "description": "0 = only list related artists on the record. 1+ = also scrape those related artists as their own records (graph crawl). Use with care, expands runs quickly.",
                        "default": 0
                    },
                    "includeDiscoveredOnPlaylists": {
                        "title": "Include 'Discovered On' playlists",
                        "type": "boolean",
                        "description": "NEW: which editorial/user playlists are driving an artist's streams (playlist attribution).",
                        "default": false
                    },
                    "includePlaylists": {
                        "title": "Resolve playlist contents",
                        "type": "boolean",
                        "description": "NEW: for playlist URLs / search results, return full track listing, owner, and follower count (paginated past 100 tracks).",
                        "default": false
                    },
                    "includeLyrics": {
                        "title": "Include lyrics",
                        "type": "boolean",
                        "description": "NEW: time-synced lyrics per track (requires a valid 'sp_dc cookie').",
                        "default": false
                    },
                    "includePodcasts": {
                        "title": "Include podcasts / episodes",
                        "type": "boolean",
                        "description": "NEW: resolve show & episode URLs (show metadata + episode list, episode metadata).",
                        "default": false
                    },
                    "includeAnalytics": {
                        "title": "★ Include deep analytics block",
                        "type": "boolean",
                        "description": "BONUS: per-artist analytics — engagement/loyalty rate, top-track concentration, estimated royalty revenue range, discovery reach, and momentum (from history). Turns raw numbers into decisions.",
                        "default": true
                    },
                    "includeContactInfo": {
                        "title": "★ Extract contact info (lead-gen)",
                        "type": "boolean",
                        "description": "BONUS: emails (from bio) + categorized social links (Instagram/TikTok/YouTube/…) + website. Solves the marketer 'who do I contact' pain that competitors sell separately.",
                        "default": true
                    },
                    "includeAppearsOn": {
                        "title": "Include 'Appears On' & 'Featuring'",
                        "type": "boolean",
                        "description": "BONUS: releases the artist appears on and playlists/releases featuring them — fuller discography graph.",
                        "default": false
                    },
                    "includeConcerts": {
                        "title": "Include concerts / tour dates (best-effort)",
                        "type": "boolean",
                        "description": "BONUS: upcoming concerts (venue, city, date). Note: Spotify gates most concert data behind a logged-in session, so anonymous runs often return an empty list.",
                        "default": false
                    },
                    "enrichRelatedArtists": {
                        "title": "Enrich related artists with monthly listeners",
                        "type": "boolean",
                        "description": "BONUS: fetch monthly listeners + rank for each related artist (adds one request per related artist).",
                        "default": false
                    },
                    "writePlayCountsCsv": {
                        "title": "Write play_counts.csv",
                        "type": "boolean",
                        "description": "BONUS/compat: also emit a flat play_counts.csv (artist_url, artist_name, album_url, album_name, track_url, track_name, play_count) to the key-value store, matching the original actor.",
                        "default": false
                    },
                    "enableHistory": {
                        "title": "★ Enable historical tracking (trends & velocity)",
                        "type": "boolean",
                        "description": "THE killer feature: persist a timestamped snapshot every run into a named dataset, then compute deltas (daily stream change) and stream velocity vs the previous run. Run this actor on a schedule to build the time-series Spotify never gives you.",
                        "default": false
                    },
                    "historyDatasetName": {
                        "title": "History store name",
                        "type": "string",
                        "description": "Named key-value store / dataset to persist snapshots into. Reused across scheduled runs to compute trends. Defaults to 'spotify-history'.",
                        "default": "spotify-history"
                    },
                    "spDcCookie": {
                        "title": "sp_dc cookie (for lyrics)",
                        "type": "string",
                        "description": "Value of the 'sp_dc' cookie from a logged-in open.spotify.com session. Only needed for lyrics. Stored as a secret."
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Optional. Proxies are included and configured automatically — leave this empty unless you want to use your own."
                    },
                    "maxConcurrency": {
                        "title": "Max concurrency",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "Parallel request workers. Keep low (3-5) to avoid 429s.",
                        "default": 4
                    },
                    "minDelayMs": {
                        "title": "Min delay between requests (ms)",
                        "minimum": 0,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Throttle to look human and avoid rate limits.",
                        "default": 350
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
