Back to skills

Spotify Api

Create and manage Spotify playlists, search music, and control playback using the Spotify Web API. UNIQUE FEATURE - Generate custom cover art images (Claude cannot generate images natively, but this skill can create SVG-based cover art for playlists). CRITICAL - When generating cover art, ALWAYS read references/COVER_ART_LLM_GUIDE.md FIRST for complete execution instructions. Use this to directly create playlists by artist/theme/lyrics, add tracks, search for music, and manage the user's Spot...

2 stars
0 votes
0 copies
0 views
Added 12/19/2025
developmentpythongobashapidocumentation

Works with

claude desktopcliapi

Install via CLI

$openskills install fabioc-aloha/spotify-skill
Download Zip
Files
SKILL.md
---
name: spotify-api
description: Create and manage Spotify playlists, search music, and control playback using the Spotify Web API. UNIQUE FEATURE - Generate custom cover art images (Claude cannot generate images natively, but this skill can create SVG-based cover art for playlists). CRITICAL - When generating cover art, ALWAYS read references/COVER_ART_LLM_GUIDE.md FIRST for complete execution instructions. Use this to directly create playlists by artist/theme/lyrics, add tracks, search for music, and manage the user's Spotify account.
---

# Spotify API Skill

**Version**: 0.9.1 | **Release Date**: October 22, 2025

## Overview

**This skill directly interacts with the Spotify Web API to manage music and playlists.**

### ⚔ Unique Capability: Image Generation

**šŸŽØ This skill can GENERATE IMAGES** - something Claude cannot do natively! It creates custom SVG-based cover art for Spotify playlists with large, readable typography optimized for thumbnail viewing. Each cover art is dynamically generated with theme-appropriate colors, gradients, and text layouts.

Use this skill when you need to:
- šŸŽØ **Generate cover art images** - Create custom playlist covers (Claude's built-in image generation limitation is bypassed!)
- šŸŽµ **Create playlists** from artist names, themes, or specific songs
- šŸ” **Search** for tracks, artists, albums
- āž• **Add/remove tracks** from playlists
- ā–¶ļø **Control playback** (play, pause, skip)
- šŸ“Š **Get user data** (profile, top tracks, listening history)

**When to use this skill:** The user wants you to create a playlist, search for music, manage their Spotify account, **or generate custom cover art images**.

## Core Capabilities

1. **šŸŽØ Cover Art Image Generation** - Generate custom images with SVG → PNG conversion (Claude cannot generate images natively!)
2. **Intelligent Playlist Creation** - Create playlists by artist, theme, lyrics, or song list
3. **Playlist Management** - Create, list, update, delete playlists
4. **Search & Discovery** - Find tracks, artists, albums, playlists
5. **Track Management** - Add/remove tracks, get recommendations
6. **Playback Control** - Play, pause, skip, control volume
7. **User Library** - Access saved tracks, profile, listening history

## Quick Start

All Spotify API operations use the `SpotifyClient` class from `scripts/spotify_client.py`. The client handles OAuth authentication and provides methods for all operations.

### Prerequisites

**1. Enable Network Access (REQUIRED)**

āš ļø **This skill requires network access to reach api.spotify.com**

In Claude Desktop, you must enable network egress:
- Go to **Settings** → **Developer** → **Allow network egress**
- Toggle it **ON** (blue)
- Under "Domain allowlist", choose either:
  - **"All domains"** (easiest), OR
  - **"Specified domains"** and add `api.spotify.com` (more secure/restricted)
- This allows the skill to make API calls to Spotify's servers

Without network access enabled, API calls will fail with connection errors.

**2. Install Dependencies**

```bash
pip install -r requirements.txt
```

Required packages:
- `requests>=2.31.0` - HTTP requests for Spotify Web API
- `python-dotenv>=1.0.0` - Environment variable management
- `cairosvg>=2.7.0` - SVG to PNG conversion for **image generation**
- `pillow>=10.0.0` - Image processing for **cover art creation**

> **šŸ’” Note:** The `cairosvg` and `pillow` packages enable **image generation** - allowing this skill to create cover art images even though Claude cannot generate images natively!

### Basic Setup

The easiest way to initialize the client is using credentials from environment variables (loaded from `.env` file):

```python
from spotify_client import create_client_from_env

# Initialize client from environment variables (.env file)
client = create_client_from_env()

# If you have a refresh token, refresh the access token
if client.refresh_token:
    client.refresh_access_token()
```

Alternatively, you can manually provide credentials:

```python
from spotify_client import SpotifyClient

# Initialize with credentials directly
client = SpotifyClient(
    client_id="YOUR_CLIENT_ID",
    client_secret="YOUR_CLIENT_SECRET",
    redirect_uri="http://localhost:8888/callback",
    refresh_token="YOUR_REFRESH_TOKEN"  # if available
)

# Refresh to get current access token
if client.refresh_token:
    client.refresh_access_token()
```

### Common Operations

**List ALL user playlists (with pagination):**
```python
# Get all playlists - handles pagination automatically
all_playlists = []
offset = 0
limit = 50  # Max allowed per request

while True:
    playlists = client.get_user_playlists(limit=limit, offset=offset)
    if not playlists:
        break  # No more playlists
    all_playlists.extend(playlists)
    offset += limit
    if len(playlists) < limit:
        break  # Last page (fewer than limit returned)

print(f"Total playlists: {len(all_playlists)}")
for playlist in all_playlists:
    print(f"- {playlist['name']} ({playlist['tracks']['total']} tracks)")
```

**Create a new playlist:**
```python
playlist = client.create_playlist(
    name="My Awesome Playlist",
    description="A curated collection",
    public=True
)
```

**Search for tracks:**
```python
results = client.search_tracks(query="artist:The Beatles", limit=20)
```

**Add tracks to playlist:**
```python
client.add_tracks_to_playlist(
    playlist_id="playlist_123",
    track_ids=["track_1", "track_2", "track_3"]
)
```

## Playlist Management Workflows

### List All User Playlists

**Important:** Users may have more than 50 playlists. Always use pagination to get ALL playlists:

```python
# Get ALL playlists using pagination
all_playlists = []
offset = 0
limit = 50  # Spotify's max per request

while True:
    batch = client.get_user_playlists(limit=limit, offset=offset)
    if not batch:
        break  # No more playlists to fetch

    all_playlists.extend(batch)
    print(f"Fetched {len(batch)} playlists (total so far: {len(all_playlists)})")

    offset += limit
    if len(batch) < limit:
        break  # Last page - fewer results than limit means we're done

print(f"\nāœ“ Total playlists found: {len(all_playlists)}")

# Display all playlists with details
for i, playlist in enumerate(all_playlists, 1):
    print(f"{i}. {playlist['name']}")
    print(f"   Tracks: {playlist['tracks']['total']}")
    print(f"   Public: {playlist['public']}")
    print(f"   ID: {playlist['id']}")
```

## Playlist Creation Workflows

### By Artist/Band Name

Create a playlist containing all or most popular tracks by a specific artist:

```python
# STEP 1: Search for the artist by name
artists = client.search_artists(query="The Beatles", limit=1)
if not artists:
    print("Artist not found")
    # Handle error: artist doesn't exist or name is misspelled
else:
    artist_id = artists[0]['id']  # Get Spotify ID of first result

    # STEP 2: Get the artist's most popular tracks
    # Note: Spotify API returns up to 10 top tracks per artist
    tracks = client.get_artist_top_tracks(artist_id=artist_id)
    track_ids = [t['id'] for t in tracks]  # Extract just the track IDs

    # STEP 3: Create a new playlist and add the tracks
    playlist = client.create_playlist(name="The Beatles Collection")
    client.add_tracks_to_playlist(playlist['id'], track_ids)
    print(f"Created playlist with {len(track_ids)} tracks")
```

### By Theme/Mood

Create thematic playlists by searching for tracks matching mood keywords:

```python
# STEP 1: Define search queries for your theme
# Spotify search syntax: "genre:indie mood:chill" or "genre:indie year:2020-2024"
theme_queries = [
    "genre:indie mood:chill",      # Search for chill indie tracks
    "genre:indie year:2020-2024"   # Search for recent indie tracks
]

# STEP 2: Search for tracks matching each query
all_tracks = []
for query in theme_queries:
    results = client.search_tracks(query=query, limit=50)  # Get up to 50 per query
    all_tracks.extend(results)  # Combine results from all queries

# STEP 3: Remove duplicates (same track may match multiple queries)
# Use set() with track IDs to keep only unique tracks
unique_track_ids = list(set(t['id'] for t in all_tracks))

# STEP 4: Create playlist with unique tracks (limit to 100 for reasonable size)
playlist = client.create_playlist(name="Chill Indie Evening")
client.add_tracks_to_playlist(playlist['id'], unique_track_ids[:100])
print(f"Created playlist with {len(unique_track_ids[:100])} tracks")
```

### By Lyrics Content

Search for tracks with specific lyrical themes using Spotify's search:

```python
# STEP 1: Define keywords related to lyrical content
# Note: Spotify search indexes track/artist names and some metadata,
# not full lyrics, so results are based on title/description matching
queries = ["love", "heartbreak", "summer", "midnight"]

# STEP 2: Search for tracks matching each keyword
all_tracks = []
for keyword in queries:
    results = client.search_tracks(query=keyword, limit=20)  # 20 tracks per keyword
    all_tracks.extend(results)

# STEP 3: Remove duplicates (same track may match multiple keywords)
# Use set() with track IDs to keep only unique tracks
unique_track_ids = list(set(t['id'] for t in all_tracks))
print(f"Found {len(all_tracks)} total matches, {len(unique_track_ids)} unique tracks")

# STEP 4: Create playlist (limit to 100 tracks for reasonable size)
playlist = client.create_playlist(name="Love & Heartbreak")
client.add_tracks_to_playlist(playlist['id'], unique_track_ids[:100])
print(f"Created playlist with {len(unique_track_ids[:100])} unique tracks")
```

### From Specific Song List

Create a playlist from a user-provided list of track URIs or search terms:

```python
# STEP 1: Get the list of songs from the user
# User provides song names (can also use Spotify URIs like "spotify:track:...")
song_list = ["Shape of You", "Blinding Lights", "As It Was"]

# STEP 2: Search for each song and collect track IDs
track_ids = []
for song_name in song_list:
    results = client.search_tracks(query=song_name, limit=1)  # Get best match
    if results:
        track_ids.append(results[0]['id'])  # Add first result's ID
        print(f"āœ“ Found: {results[0]['name']} by {results[0]['artists'][0]['name']}")
    else:
        print(f"āœ— Not found: {song_name}")  # Song doesn't exist or name is wrong

# STEP 3: Create playlist with found tracks
playlist = client.create_playlist(name="My Favorites")
if track_ids:
    client.add_tracks_to_playlist(playlist['id'], track_ids)
    print(f"Created playlist with {len(track_ids)}/{len(song_list)} tracks")
else:
    print("No tracks found - playlist is empty")
```

## šŸŽØ Cover Art Image Generation

> **⚔ UNIQUE CAPABILITY: This skill can generate images!**
>
> Claude cannot generate images natively, but this skill bypasses that limitation by creating custom SVG graphics and converting them to PNG images for Spotify playlist covers.

> **🚨 MANDATORY: USE THE COVER ART LLM GUIDE**
>
> **āš ļø DO NOT attempt to generate cover art without first reading the complete execution guide.**
>
> **āž”ļø READ THIS FILE FIRST: [references/COVER_ART_LLM_GUIDE.md](references/COVER_ART_LLM_GUIDE.md)**
>
> **This guide is REQUIRED and contains:**
> - Complete step-by-step execution instructions
> - How to analyze playlist content to determine appropriate colors
> - Genre-to-color and mood-to-color mapping tables
> - Typography rules and accessibility requirements
> - Edge case handling and quality checklist
>
> **Do not proceed with cover art generation without consulting this guide first.**

### āš ļø Required Scope for Upload

**To upload cover art to Spotify, you MUST have the `ugc-image-upload` scope enabled:**

1. Go to [Spotify Developer Dashboard](https://developer.spotify.com/dashboard)
2. Select your app
3. Ensure `ugc-image-upload` scope is included in your authorization
4. Re-run OAuth flow to get a new refresh token with this scope: `python get_refresh_token.py`
5. Update your `.env` file with the new refresh token

**Without this scope:** You'll get a 401 error when trying to upload. However, you can still **generate cover art images locally** and upload them manually via Spotify's web/mobile app.

**šŸ“– Having trouble?** See [COVER_ART_TROUBLESHOOTING.md](COVER_ART_TROUBLESHOOTING.md) for detailed solutions.

### Basic Usage Example

**āš ļø Remember: Read [references/COVER_ART_LLM_GUIDE.md](references/COVER_ART_LLM_GUIDE.md) before generating cover art!**

```python
from cover_art_generator import CoverArtGenerator

# Initialize generator (uses same credentials as SpotifyClient)
art_gen = CoverArtGenerator(client_id, client_secret, access_token)

# Generate and upload cover art
# (Follow the LLM guide for how to determine appropriate colors)
art_gen.create_and_upload_cover(
    playlist_id=playlist['id'],
    title="Beast Mode",           # Main title (large text)
    subtitle="Gym",                # Optional subtitle
    gradient_start="#E63946",      # Colors determined from guide
    gradient_end="#1D1D1D",
    text_color="#FFFFFF"
)
```

**All cover art generation workflows, color selection guidance, and advanced features are documented in [references/COVER_ART_LLM_GUIDE.md](references/COVER_ART_LLM_GUIDE.md).**

## Advanced Operations

### Get Recommendations

```python
# Get AI-powered music recommendations based on seed artists/tracks/genres
recommendations = client.get_recommendations(
    seed_artists=["artist_id_1"],  # Spotify IDs of artists
    seed_tracks=["track_id_1"],    # Spotify IDs of tracks
    limit=50                       # Number of recommendations to get
)
# Returns: List of recommended tracks similar to the seeds
```

### Access User Profile

```python
# Get information about the current authenticated user
profile = client.get_current_user()
# Returns: user_id, display_name, email, followers, images, country, etc.
print(f"Logged in as: {profile['display_name']}")
print(f"User ID: {profile['id']}")
```

### Get User's Top Items

```python
# Get user's most played artists over different time periods
top_artists = client.get_top_items(
    item_type="artists",
    limit=20,
    time_range="medium_term"  # Options: short_term (~4 weeks), medium_term (~6 months), long_term (~years)
)
print(f"Top artist: {top_artists[0]['name']}")

# Get user's most played tracks
top_tracks = client.get_top_items(
    item_type="tracks",
    limit=20,
    time_range="short_term"  # Recent listening (last ~4 weeks)
)
print(f"Most played track: {top_tracks[0]['name']} by {top_tracks[0]['artists'][0]['name']}")
```

### Playback Control

```python
# STEP 1: Start playback of a playlist or album
client.start_playback(
    device_id="device_123",                      # Optional: specific device
    context_uri="spotify:playlist:playlist_id",  # What to play (playlist/album/artist URI)
    offset=0                                     # Optional: start at track 0
)

# STEP 2: Pause playback
client.pause_playback(device_id="device_123")

# STEP 3: Skip to next track
client.next_track(device_id="device_123")

# STEP 4: Check what's currently playing
current = client.get_currently_playing()
if current and current.get('item'):
    track = current['item']
    print(f"Now playing: {track['name']} by {track['artists'][0]['name']}")
else:
    print("Nothing is currently playing")
```

## Authentication & Credentials

See `references/authentication_guide.md` for detailed OAuth flow setup and credential management. Ensure credentials are available in environment variables or passed at initialization:

- `SPOTIFY_CLIENT_ID`
- `SPOTIFY_CLIENT_SECRET`
- `SPOTIFY_REDIRECT_URI`
- `SPOTIFY_ACCESS_TOKEN` (optional, can use refresh token)
- `SPOTIFY_REFRESH_TOKEN` (for token refresh)

## API Reference

See `references/api_reference.md` for complete Spotify API endpoint documentation, rate limits, response formats, and error handling patterns.

## Scripts

### spotify_client.py

Comprehensive Python wrapper for all Spotify Web API operations. Handles authentication, token management, rate limiting, and provides methods for:
- Authentication and token refresh
- Playlist CRUD operations
- Search (tracks, artists, albums, playlists)
- Track/URI management
- User data access
- Playback control
- Recommendations engine

### playlist_creator.py

High-level utility for intelligent playlist creation from various sources (artist, theme, lyrics, song list). Encapsulates common workflows and handles track deduplication and limit management.

---

## For Developers Building Apps (Advanced)

**Note:** The features below are for developers building web applications, NOT for direct playlist creation tasks.

If the user is asking you to **build an application** or **export data**, see:
- `ADVANCED_USAGE.md` - Application development patterns
- `scripts/export_data.py` - Export Spotify data as JSON
- `SpotifyAPIWrapper` class - Error handling for production apps

**For playlist creation and music management, use the workflows above.**

Comments (0)

No comments yet. Be the first to comment!