Metadata-Version: 2.4
Name: innerspot
Version: 0.0.1.dev2
Summary: Spotify internal API client using protobuf, GraphQL, and web scraping.
Project-URL: Homepage, https://github.com/viperadnan-git/innerspot
Project-URL: Repository, https://github.com/viperadnan-git/innerspot
Project-URL: Issues, https://github.com/viperadnan-git/innerspot/issues
Author-email: Adnan Ahmad <viperadnan@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: api,client,graphql,metadata,music,protobuf,spotify
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx>=0.28.1
Requires-Dist: protobuf>=5.29.0
Requires-Dist: pydantic>=2.10.0
Description-Content-Type: text/markdown

# innerspot

A Python client for Spotify's internal APIs using protobuf, GraphQL, and web scraping.

## Installation

```bash
pip install innerspot
```

## Quick Start

```python
from innerspot import SpotifyClient

# No auth needed for basic metadata and search
with SpotifyClient() as client:
    track = client.get_track("4PTG3Z6ehGkBFwjybzWkR8")
    print(f"{track.name} by {track.artists[0].name}")

    album = client.get_album("6PFPjumGRpZnBzqnDci6qJ")
    print(f"{album.name} ({album.total_tracks} tracks)")

    artist = client.get_artist("06HL4z0CvFAxyc27GXpf02")
    print(f"{artist.name} - {artist.popularity} popularity")

    results = client.search("Never Gonna Give You Up")
    print(f"{len(results.tracks.items)} tracks found")
```

### Authentication

**SpotifyWeb** (default) — uses the web player's TOTP auth flow:

```python
from innerspot import SpotifyClient, SpotifyWeb

# Anonymous (metadata, search, home sections)
client = SpotifyClient()

# With sp_dc cookie (adds lyrics, radio, spclient search)
client = SpotifyClient(auth=SpotifyWeb(sp_dc="your_sp_dc_cookie"))
```

**SpotifyEmbed** — simpler embed page token (no TOTP, limited permissions):

```python
from innerspot import SpotifyClient, SpotifyEmbed

client = SpotifyClient(auth=SpotifyEmbed())
```

**SpotifyPKCE** — full account access with interactive OAuth login:

```python
from innerspot import SpotifyClient, SpotifyPKCE

auth = SpotifyPKCE()  # opens browser for login
client = SpotifyClient(auth=auth)
```

## Features

- **Tracks**: `get_track()`, `get_isrc_track()`, radio/recommendations
- **Albums**: `get_album()`, new releases
- **Artists**: `get_artist()`, `get_artists()`, `get_artist_discography()`
- **Playlists**: `get_playlist()`, `get_playlist_with_tracks()`, user playlists
- **Search**: `search()`, `search_genre()`
- **Lyrics**: `get_lyrics()` (requires sp_dc)
- **Browse**: `get_home_sections()`, `get_charts()`, `get_featured_playlists()`
- **Radio**: `get_radio()`, `iter_genre_tracks()`, `iter_artist_radio()`, `iter_track_radio()`

## Data Providers

Providers are accessible directly or through convenience methods with fallback:

```python
# Direct provider access
track = client.spclient.get_track("4PTG3Z6ehGkBFwjybzWkR8")
track = client.partner.get_track("4PTG3Z6ehGkBFwjybzWkR8")

# Convenience with fallback (spclient → partner → scraping)
track = client.get_track("4PTG3Z6ehGkBFwjybzWkR8")

# Low-level 1:1 API access
data = client.spclient.extended_metadata([(uri, kind, cls)])
results = client.spclient.search("test")
lyrics = client.spclient.color_lyrics("4PTG3Z6ehGkBFwjybzWkR8")
```

1. **SpClientProvider** (protobuf) — Spotify's internal metadata API, highest fidelity
2. **PartnerProvider** (GraphQL) — Spotify's partner API, includes play counts and search
3. **ScrapingProvider** (HTML) — Fallback via open.spotify.com page scraping

## Token Caching

Tokens are cached to `.innerspot.cache` by default. Custom cache handlers:

```python
from innerspot import SpotifyClient, SpotifyWeb, MemoryCacheHandler

client = SpotifyClient(
    auth=SpotifyWeb(cache_handler=MemoryCacheHandler())
)
```

## Disclaimer

> [!WARNING]
> This library uses Spotify's **internal, undocumented APIs** that are not intended for third-party use. These APIs can change or break without notice.
>
> - This project is for **educational and research purposes only**
> - Using this library may violate [Spotify's Terms of Service](https://www.spotify.com/legal/end-user-agreement/) and [Developer Terms](https://developer.spotify.com/terms)
> - Your Spotify account could be **suspended or banned**
> - The authors assume **no liability** for any consequences of using this software
> - Do **not** use this for commercial purposes or at scale
>
> **By using this library, you accept full responsibility for any consequences.**

## License

[MIT](LICENSE)
