Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
Spotify Web API client for Nyx agents. Use when interacting with Spotify: search, playback, playlists, library, tracks, artists, albums, shows, podcasts. Req...
Spotify Web API client for Nyx agents. Use when interacting with Spotify: search, playback, playlists, library, tracks, artists, albums, shows, podcasts. Req...
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete.
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run.
A lightweight Spotify Web API client using direct HTTP requests. No Spotipy dependency.
# Install dependencies pip install requests python-dotenv # Add to path import sys sys.path.insert(0, "skills/spoticlaw/scripts") from spoticlaw import player, search, playlists, library # Search for music results = search().query("coldplay", types=["track"], limit=10) # Play a track player().play(uris=["spotify:track:..."]) # Manage playlists playlists().create("My Playlist") playlists().add_items("playlist_id", ["spotify:track:..."]) # Save to library library().save(["spotify:track:..."]) Or run from the scripts directory: cd skills/spoticlaw/scripts python -c "from spoticlaw import player; player().play(...)"
Required env vars in agent runtime: SPOTIFY_CLIENT_ID SPOTIFY_CLIENT_SECRET SPOTIFY_REDIRECT_URI (recommended: http://127.0.0.1:8888/callback) Required file: .spotify_cache (OAuth token cache)
Security Note: Tokens never pass through the AI model. Authentication is done locally, and the token file is copied manually to the agent.
Create a Spotify app at https://developer.spotify.com/dashboard Get CLIENT_ID and CLIENT_SECRET Add http://127.0.0.1:8888/callback as Redirect URI Create .env file in your LOCAL machine: SPOTIFY_CLIENT_ID=your_client_id SPOTIFY_CLIENT_SECRET=your_client_secret SPOTIFY_REDIRECT_URI=http://127.0.0.1:8888/callback Run authentication on your LOCAL machine: cd skills/spoticlaw/scripts pip install -r requirements.txt python auth.py Open the displayed URL in your browser, authorize Copy the token file to your agent: # Linux/Mac - copy to agent's skill folder cp .spotify_cache /path/to/agent/skills/spoticlaw/.spotify_cache # Or if agent is remote, copy via scp, USB, etc. scp .spotify_cache user@agent:/path/to/skills/spoticlaw/.spotify_cache That's it! No token ever touches the AI. The agent just reads the file.
The library automatically handles token refresh only if the agent has the same app credentials in .env: Access token expires after ~1 hour On first API call after expiry, it uses refresh_token + client credentials to request a new access token Requires SPOTIFY_CLIENT_ID and SPOTIFY_CLIENT_SECRET in the agent environment If .spotify_cache exists but .env is missing/mismatched, refresh fails (invalid_client) If you get an error, run python auth.py locally again and copy updated .spotify_cache For more on Spotify's OAuth flow, see: https://developer.spotify.com/documentation/web-api/tutorials/code-flow
The auth.py script requests these scopes: user-read-playback-state - Read playback state user-modify-playback-state - Control playback playlist-read-private - Read private playlists playlist-modify-public - Modify public playlists playlist-modify-private - Modify private playlists user-library-read - Read user library user-library-modify - Modify user library user-read-recently-played - Recently played tracks user-top-read - Top tracks/artists user-follow-read - Followed artists
Important: Add the module path and install deps first: pip install requests python-dotenv # Install dependencies # For agent execution, add to path: import sys sys.path.insert(0, "skills/spoticlaw/scripts")
from spoticlaw import user user().me() # Get current user profile Returns: {id, display_name, email, country, ...}
from spoticlaw import search # Search for tracks search().query("song name", types=["track"], limit=10) # Search for artists search().query("artist name", types=["artist"], limit=10) # Search multiple types search().query("coldplay", types=["track", "artist", "album"], limit=10) Parameters: q: Search query string types: List of types: track, artist, album, playlist, show, episode, audiobook limit: Max 10 results (Spotify limit) offset: Pagination offset
from spoticlaw import tracks tracks().get("track_id") # Get single track tracks().get_multiple(["id1", "id2"]) # Get multiple tracks Returns track metadata: {name, artists, album, duration_ms, uri, ...}
from spoticlaw import artists artists().get("artist_id") # Get artist details artists().get_albums("artist_id", limit=10) # Get artist albums Album filters (include_groups): album, single, compilation, appears_on
from spoticlaw import albums albums().get("album_id") # Get album details albums().get_tracks("album_id") # Get album tracks
from spoticlaw import shows shows().get("show_id") # Get show details shows().get_episodes("show_id", limit=10) # Get show episodes
from spoticlaw import episodes episodes().get("episode_id") # Get episode details
from spoticlaw import playlists, user_playlists # Get user's playlists user_playlists().get(limit=50) # Get playlist details playlists().get("playlist_id") # Get playlist tracks # Note: Each item has 'item' key (not 'track'), e.g. item['item']['name'] # Also can contain episodes (podcasts), not just tracks playlists().get_items("playlist_id", limit=50) # Create playlist playlists().create(name="My Playlist", description="...", public=False) # Update playlist playlists().update("playlist_id", name="New Name") # Add tracks playlists().add_items("playlist_id", ["spotify:track:...", "spotify:track:..."]) # Remove tracks playlists().remove_items("playlist_id", ["spotify:track:..."]) # Delete playlist (unfollow) playlists().delete("playlist_id")
from spoticlaw import library library().save(["spotify:track:..."]) # Save to library library().remove(["spotify:track:..."]) # Remove from library library().check(["spotify:track:..."]) # Check if saved, returns [True, False]
from spoticlaw import player # Get playback state player().get_playback_state() # Returns {} if nothing playing player().get_currently_playing() # Get devices player().get_devices() # Returns list of devices with IDs # Transfer playback to device player().transfer("device_id", play=True) # Playback control player().play(uris=["spotify:track:..."]) # Start playing player().play(context_uri="spotify:album:...") # Play album/playlist player().pause() player().next() player().previous() player().seek(60000) # Seek to 1:00 (milliseconds) player().set_volume(80) # Set volume 0-100 # Queue player().add_to_queue("spotify:track:...") player().get_queue() # Modes player().set_shuffle(True) player().set_repeat("off") # off, track, context # Recently played player().get_recently_played(limit=50)
from spoticlaw import personalisation personalisation().get_top("tracks", time_range="medium_term", limit=20) personalisation().get_top("artists", time_range="long_term", limit=20) # time_range: short_term (4 weeks), medium_term (6 months), long_term (years)
from spoticlaw import follow follow().get_followed(limit=50) # Get followed artists
The primitives can be mixed and matched to create powerful automations. Here are practical examples:
from spoticlaw import search, player # 1. Search for the song results = search().query("stairway to heaven", types=["track"], limit=5) song = results["tracks"]["items"][0] song_uri = song["uri"] print(f"Playing: {song['name']} by {song['artists'][0]['name']}") # 2. Play it player().play(uris=[song_uri])
from spoticlaw import search, playlists # 1. Search for songs results = search().query("led zeppelin", types=["track"], limit=10) track_uris = [t["uri"] for t in results["tracks"]["items"][:5]] # 2. Create playlist pl = playlists().create("Led Zeppelin Mix", public=False) playlist_id = pl["id"] # 3. Add tracks playlists().add_items(playlist_id, track_uris) print(f"Created playlist: {pl['name']}")
from spoticlaw import artists, albums, library # 1. Find artist artist = search().query("the weeknd", types=["artist"], limit=1)["artists"]["items"][0] # 2. Get albums albums_list = artists().get_albums(artist["id"], include_groups="album", limit=5) # 3. Save first album album = albums_list["items"][0] library().save([album["uri"]]) print(f"Saved album: {album['name']}")
from spoticlaw import search, shows, player # 1. Find podcast podcast = search().query("joe rogan", types=["show"], limit=1)["shows"]["items"][0] show_id = podcast["id"] # 2. Get latest episode episodes = shows().get_episodes(show_id, limit=1) episode = episodes["items"][0] episode_uri = episode["uri"] # 3. Get device and play devices = player().get_devices() if devices.get("devices"): device_id = devices["devices"][0]["id"] player().transfer(device_id, play=True) player().play(uris=[episode_uri]) print(f"Playing: {episode['name']}")
from spoticlaw import player, search # 1. Get available devices devices = player().get_devices() print("Available devices:", [d["name"] for d in devices.get("devices", [])]) # 2. Transfer to phone if devices.get("devices"): device_id = devices["devices"][0]["id"] player().transfer(device_id, play=True) # 3. Search and play results = search().query("dream on", types=["track"], limit=1) track_uri = results["tracks"]["items"][0]["uri"] player().play(uris=[track_uri])
from spoticlaw import personalisation, search, library # 1. Get top artists top = personalisation().get_top("artists", limit=10) print("Your top artists:") for i, a in enumerate(top["items"], 1): print(f" {i}. {a['name']}") # 2. Search for a new artist new_artist = search().query("tame impala", types=["artist"], limit=1)["artists"]["items"][0] print(f"\nFound: {new_artist['name']}") # Note: Follow functionality requires additional scope (not in current scope list) # Use Spotify app to follow manually
from spoticlaw import albums, player # 1. Get album tracks album_id = "4aawyAB9vmqN3uQ7FjRGTy" # Example album tracks = albums().get_tracks(album_id) # 2. Add all tracks to queue for track in tracks["items"][:5]: # First 5 tracks player().add_to_queue(track["uri"]) print("Added 5 tracks to queue")
from spoticlaw import library, search # 1. Search for tracks results = search().query("classic rock", types=["track"], limit=20) track_uris = [t["uri"] for t in results["tracks"]["items"]] # 2. Check which are in library saved = library().check(track_uris) # 3. Show results for i, (track, is_saved) in enumerate(zip(results["tracks"]["items"], saved)): status = "โ saved" if is_saved else "โ not saved" print(f"{i+1}. {track['name']} - {status}")
from spoticlaw import player, library # 1. Get recently played recent = player().get_recently_played(limit=10) print("Recently played:") for i, item in enumerate(recent["items"], 1): track = item["track"] print(f" {i}. {track['name']} - {track['artists'][0]['name']}") # 2. Save the first one if recent["items"]: track_uri = recent["items"][0]["track"]["uri"] library().save([track_uri]) print(f"\nSaved: {recent['items'][0]['track']['name']}")
from spoticlaw import playlists, player # 1. Get user's playlists my_playlists = user_playlists().get(limit=10) print("Your playlists:") for p in my_playlists["items"]: print(f" - {p['name']} ({p['tracks']['total']} tracks)") # 2. Pick first playlist and play if my_playlists["items"]: playlist_id = my_playlists["items"][0]["id"] # Get device first devices = player().get_devices() if devices.get("devices"): player().transfer(devices["devices"][0]["id"], play=True) # Play playlist player().play(context_uri=f"spotify:playlist:{playlist_id}") print(f"Playing: {my_playlists['items'][0]['name']}")
from spoticlaw import player, SpotifyException try: player().play(uris=["spotify:track:..."]) except SpotifyException as e: if "NO_ACTIVE_DEVICE" in str(e): print("No device found. Open Spotify and try again.") elif "Invalid token" in str(e): print("Token expired. Re-authenticate: python auth.py") else: print(f"Error: {e}")
ErrorSolutionNo token. Re-authenticate.Run python auth.pyThe access token expiredShould auto-refresh. If not, run python auth.pyInsufficient client scopeRe-auth with more scopesNO_ACTIVE_DEVICEOpen Spotify app, then retryInvalid limitUse max 10 for search, 50 for playlistsResource not foundInvalid ID or item unavailable
Search: max 10 results Playlist items: max 50 Pagination: Use offset parameter Player: Requires active Spotify session
scripts/spoticlaw.py - Main API client scripts/auth.py - Authentication helper scripts/requirements.txt - Dependencies
For setup, troubleshooting, and contributions: https://github.com/your-org/spoticlaw
Code helpers, APIs, CLIs, browser automation, testing, and developer operations.
Largest current source with strong distribution and engagement signals.