A python wrapper for the public & private Spotify API
Find a file
shepardxia bc61503a57 Resolve missing track metadata on status queries
Queue and history tracks from Spotify's Connect State API often arrive
without metadata. Now _query_status resolves titles, artists, and albums
on demand via the GraphQL getTrack endpoint, with URI dedup to avoid
redundant calls.
2026-03-07 00:32:31 -05:00
clautify Resolve missing track metadata on status queries 2026-03-07 00:32:31 -05:00
tests Rename test_dsl_v4.py → test_dsl.py (no v1/v3 exist, artifact of iteration) 2026-03-06 17:42:29 -05:00
.gitignore Housekeeping: migrate to pyproject.toml, strip fork artifacts 2026-02-11 20:02:49 -05:00
.pre-commit-config.yaml Rewrite DSL tests, add pre-commit hooks and ruff formatting 2026-02-07 16:36:37 -05:00
LICENSE Clean up 2024-07-08 20:55:10 +05:30
pyproject.toml Remove dead code, debloat DSL v4, and consolidate tests 2026-02-25 19:07:46 -05:00
README.md Housekeeping: migrate to pyproject.toml, strip fork artifacts 2026-02-11 20:02:49 -05:00
uv.lock Add name cache, auth retry, max volume cap, and expanded DSL 2026-02-11 20:03:41 -05:00

clautify

A DSL-driven Spotify controller. One command string does what used to take five API calls.

Built on SpotAPI by Aran — a reverse-engineered Spotify Connect client that requires no Premium and no API key. We added a Lark grammar DSL, stripped unused modules, and renamed the package.

Note: This project is intended solely for educational purposes. Accessing private endpoints without authorization may violate Spotify's terms of service.

Setup

1. Install

pip install -e .

Requires Python 3.10+.

  1. Open open.spotify.com in your browser and log in
  2. Open DevTools (F12) → ApplicationCookieshttps://open.spotify.com
  3. Copy the value of sp_dc

3. Save it (one-time)

from clautify.dsl import SpotifySession

SpotifySession.setup("paste_your_sp_dc_here")
# Saved to ~/.config/clautify/session.json

The sp_dc cookie typically lasts ~1 year. Re-run setup() if it expires.

4. Use it

session = SpotifySession.from_config()

session.run('play "Bohemian Rhapsody" volume 70 mode shuffle')
session.run('search "jazz" artists limit 5')
session.run('add spotify:track:abc to spotify:playlist:def')

session.close()

Every run() call returns {"status": "ok", ...} or raises DSLError.

Command Reference

Actions (mutate state)

Command Example
play play "Bohemian Rhapsody" / play spotify:track:abc in spotify:playlist:def
pause / resume pause
skip skip 3 / skip -1 (backwards)
seek seek 30000 (ms)
queue queue "Stairway to Heaven"
like / unlike like spotify:track:abc
follow / unfollow follow spotify:artist:abc
save / unsave save spotify:playlist:abc
add ... to add spotify:track:abc to spotify:playlist:def
remove ... from remove spotify:track:abc from spotify:playlist:def
create playlist create playlist "Road Trip"
delete playlist delete playlist spotify:playlist:abc

State modifiers compose with any action (or stand alone):

play "jazz" volume 70 mode shuffle on "Kitchen Speaker"
volume 50 mode repeat

Queries (read state)

Command Example
search search "jazz" artists limit 5 offset 10
now playing now playing
get queue get queue
get devices get devices
library library playlists limit 20
info info spotify:track:abc
history history limit 10
recommend recommend 10 for spotify:playlist:abc

Query modifiers: limit N and offset N compose with queries only.

Grammar Rules

  • Targets are either Spotify URIs (spotify:track:abc) or quoted strings ("Bohemian Rhapsody")
  • Quoted strings are auto-resolved via search — no need to look up URIs first
  • State modifiers (volume, mode, device/on) only compose with actions
  • Query modifiers (limit, offset) only compose with queries
  • Mixing them is a parse error

Credits

Built on SpotAPI by Aran — reverse-engineered Spotify Connect API client. Original codebase provided the HTTP layer, login, player, and all Spotify endpoint wrappers. We added the Lark DSL layer and stripped unused modules.

License

This project is licensed under the GPL 3.0 License. See LICENSE for details.