https://github.com/alertua/bandcamp_async_api
Asynchronous Python client for the Bandcamp API.
https://github.com/alertua/bandcamp_async_api
aiohttp api async bandcamp python
Last synced: 3 months ago
JSON representation
Asynchronous Python client for the Bandcamp API.
- Host: GitHub
- URL: https://github.com/alertua/bandcamp_async_api
- Owner: ALERTua
- Created: 2025-12-21T19:03:49.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2026-01-26T17:14:07.000Z (5 months ago)
- Last Synced: 2026-01-27T05:32:57.094Z (5 months ago)
- Topics: aiohttp, api, async, bandcamp, python
- Language: Python
- Homepage: https://github.com/ALERTua/bandcamp_async_api
- Size: 144 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
[](https://stand-with-ukraine.pp.ua)
[](https://stand-with-ukraine.pp.ua)
[](https://stand-with-ukraine.pp.ua)
[](https://stand-with-ukraine.pp.ua)
# Bandcamp Async API
A modern, asynchronous Python client for the Bandcamp API.
###### This project was created to [implement](https://github.com/music-assistant/server/pull/2871) a Bandcamp music provider for [Music Assistant](https://github.com/music-assistant), enabling seamless integration of Bandcamp's music catalog into home audio systems.
- **Repository**: https://github.com/ALERTua/bandcamp_async_api
- **Changelog**: https://github.com/ALERTua/bandcamp_async_api/releases
- **PyPI**: https://pypi.org/project/bandcamp_async_api/
- **Music Assistant**: https://github.com/music-assistant
## Features
- **Search**: Search for artists, albums, and tracks across Bandcamp
- **Albums**: Retrieve detailed album information including track listings
- **Tracks**: Get individual track details and streaming information
- **Artists**: Access artist profiles, discographies, and metadata
- **Collections**: Browse user collections and wishlists (auth required for private data)
- **Following**: Access following bands, following fans, and followers
- **Feed**: Get personalized music feed with new releases from followed artists
- **Async**: Fully asynchronous API using aiohttp
- **Type-safe**: Complete type hints for all models and methods
- **Well-tested**: Comprehensive test suite with real API data
## Installation
Install from PyPI:
```bash
pip install bandcamp-async-api
```
Or using uv:
```bash
uv add bandcamp-async-api
```
## Quick Start
```python
import asyncio
from bandcamp_async_api import BandcampAPIClient
async def main():
async with BandcampAPIClient(identity_token='7%09optional_identity_token%7D') as client:
# Search for music
results = await client.search("radiohead")
print(f"Found {len(results)} results")
# Get album details
if results:
album_result = next(r for r in results if r.type == "album")
album = await client.get_album(album_result.artist_id, album_result.id)
print(f"Album: {album.title} by {album.artist.name}")
# Get artist information
artist_result = next(r for r in results if r.type == "artist")
artist = await client.get_artist(artist_result.id)
print(f"Artist: {artist.name} - {artist.bio}")
if __name__ == '__main__':
asyncio.run(main())
```
## Authentication
For accessing user collections, you need to obtain an identity token from Bandcamp cookies:
```python
from bandcamp_async_api import BandcampAPIClient
client = BandcampAPIClient(identity_token="your_identity_token")
```
## Music Feed
The `get_feed()` method retrieves a personalized music feed containing new releases from followed artists, fan purchases, and fan picks. This endpoint requires authentication - you must provide an identity token.
```python
import asyncio
from bandcamp_async_api import BandcampAPIClient, BandcampMustBeLoggedInError
async def main():
async with BandcampAPIClient(identity_token='your_identity_token') as client:
# Get your music feed
feed = await client.get_feed()
print(f"New stories: {len(feed.stories)}")
print(f"Has more: {feed.has_more}")
# Iterate through feed stories
for story in feed.stories:
print(f" - {story.story_type}: {story.item_title} by {story.band_name}")
# Access tracks with streaming URLs
for track in feed.track_list:
print(f" Track: {track.title} - {track.streaming_url}")
# Paginate through older stories
if feed.has_more and feed.oldest_story_date:
older_feed = await client.get_feed(older_than=feed.oldest_story_date)
print(f"Older stories: {len(older_feed.stories)}")
if __name__ == '__main__':
asyncio.run(main())
```
### Feed Story Types
The feed contains different story types:
- `np` - New track/track release
- `nr` - New album release
- `p` - Fan purchase
- `fp` - Fan pick
### Error Handling
The feed endpoint requires authentication. If you try to access it without an identity token, you'll receive a `BandcampMustBeLoggedInError`:
```python
from bandcamp_async_api import BandcampAPIClient, BandcampMustBeLoggedInError
async def safe_get_feed():
client = BandcampAPIClient() # No identity token
try:
feed = await client.get_feed()
except BandcampMustBeLoggedInError:
print("Feed requires authentication - provide an identity token")
```
## API Reference
### Core Client
- `BandcampAPIClient()` - Main API client
- `search(query: str)` - Search Bandcamp
- `get_album(artist_id, album_id)` - Get album details
- `get_track(artist_id, track_id)` - Get track details
- `get_artist(artist_id)` - Get artist details
- `get_collection_summary()` - Get collection overview
- `get_collection_items(collection_type, older_than_token, count, fan_id)` - Get collection/wishlist/following items with pagination
- `get_artist_discography(artist_id)` - Get artist's complete discography
- `get_feed(older_than)` - Get personalized music feed with pagination support
### Data Models
- `SearchResultItem` - Base search result
- `BCAlbum` - Album with tracks and metadata
- `BCTrack` - Individual track information
- `BCArtist` - Artist/band profile
- `CollectionSummary` - User's collection data
- `CollectionItem` - Individual collection item
- `FollowingItem` - Band/artist from following list
- `FanItem` - Fan/user from following_fans or followers
- `FeedResponse` - User's music feed with stories and tracks
- `FeedStory` - Individual feed story (new release, fan purchase, etc.)
- `FeedTrack` - Track from feed with streaming URL
- `FeedBandInfo` - Band information referenced in feed
- `FeedFanInfo` - Fan information referenced in feed
### Exceptions
- `BandcampAPIError` - Base API error
- `BandcampNotFoundError` - Resource not found
- `BandcampBadQueryError` - Invalid search query
- `BandcampRateLimitError` - Rate limit exceeded (includes `retry_after` attribute)
## Error Handling
The client provides specific exception types for different error conditions:
```python
from bandcamp_async_api import (
BandcampAPIClient,
BandcampNotFoundError,
BandcampAPIError
)
async def safe_get_album(client, artist_id, album_id):
try:
return await client.get_album(artist_id, album_id)
except BandcampNotFoundError:
print("Album not found")
return None
except BandcampAPIError as e:
print(f"API error: {e}")
return None
```
### Rate Limiting
When Bandcamp's API rate limit is exceeded, a `BandcampRateLimitError` is raised with a `retry_after` attribute indicating how many seconds to wait before retrying:
```python
import asyncio
from bandcamp_async_api import BandcampAPIClient, BandcampRateLimitError
async def get_album_with_retry(client, artist_id, album_id, max_retries=3):
for attempt in range(max_retries):
try:
return await client.get_album(artist_id, album_id)
except BandcampRateLimitError as e:
if attempt < max_retries - 1:
wait_time = e.retry_after or 30
print(f"Rate limited. Waiting {wait_time} seconds...")
await asyncio.sleep(wait_time)
else:
raise
```
For automatic retries with exponential backoff, you can use the `tenacity` library:
```python
from tenacity import retry, retry_if_exception_type, wait_exponential
from bandcamp_async_api import BandcampAPIClient, BandcampRateLimitError
@retry(
retry=retry_if_exception_type(BandcampRateLimitError),
wait=wait_exponential(multiplier=1, min=30, max=300)
)
async def get_album(client, artist_id, album_id):
return await client.get_album(artist_id, album_id)
```
## Development
### Setup
```bash
# Clone the repository
git clone https://github.com/ALERTua/bandcamp_async_api.git
cd bandcamp_async_api
# Install dependencies
uv sync --dev
# Run tests
uv run pytest
# Run linting
uv run ruff check
```
### Testing
The project includes comprehensive tests:
```bash
# Run all tests
uv run pytest
# Run integration tests (requires real API access)
echo "BANDCAMP_IDENTITY_TOKEN=7%09identity_token%7D" > .env
uv run pytest tests/real_data/
```
## Contributing
Contributions are welcome! Please:
1. Fork the repository
2. Create a feature branch
3. Add tests for new functionality
4. Ensure all tests pass
5. Submit a pull request
This project is built based on data from:
- https://github.com/michaelherger/Bandcamp-API
- https://github.com/impliedchaos/mopidy-bandcamp