Modern Python client for the Discogs API
Project description
discogs-sdk
discogs-sdk is a modern Python client for the Discogs API with full endpoint coverage, a fluent chainable syntax, and built-in response caching.
from discogs_sdk import Discogs
with Discogs() as client:
release = client.releases.get(352665)
print(f"{release.title} ({release.year})")
for result in client.search(query="Nine Inch Nails", type="artist"):
print(result.title)
Installation
pip install discogs-sdk
# or
uv add discogs-sdk
Requires Python 3.10+.
Features
- Full API Coverage — Every endpoint in the Discogs API v2
- Fluent API — Chain sub-resources naturally:
client.releases.get(id).rating.get() - Lazy Loading — No HTTP calls until you actually need the data
- Effortless Pagination — Browse results without managing pages or offsets
- Rate Limit Friendly — Automatically stay within API limits
- Built-in Caching — Optional TTL-based caching reduces API calls
- Flexible Auth — Supports personal tokens, consumer key/secret, or full OAuth 1.0a
- Type Safe — Get autocomplete and IDE support
- Async & Sync — Full support for both synchronous and asynchronous workflows
How it compares
| discogs-sdk | python3-discogs-client | |
|---|---|---|
| Full API coverage | ✓ | Partial |
| Fluent sub-resource chaining | ✓ | ✗ |
| Lazy loading | ✓ | ✗ |
| Auto-pagination | ✓ | ✓ |
| Automatic rate limit handling | ✓ | ✗ |
| Caching | ✓ | ✗ |
| OAuth 1.0a | ✓ | ✓ |
| Type safe (Pydantic models) | ✓ | ✗ |
| Async & sync | ✓ | ✗ |
Quick start
Authentication
Set your personal access token from your Discogs developer settings as an environment variable:
export DISCOGS_TOKEN="your-token-here"
from discogs_sdk import Discogs
client = Discogs() # reads DISCOGS_TOKEN from environment
You can also pass credentials explicitly:
client = Discogs(token="your-token-here")
The SDK supports three auth modes: personal token, consumer key/secret, and OAuth 1.0a. Credentials passed to the constructor take precedence over environment variables (DISCOGS_TOKEN, DISCOGS_CONSUMER_KEY, etc.). See examples/authentication.py for the full OAuth flow.
[!TIP] Use a
.envfile with python-dotenv or direnv to avoid exporting tokens manually in every shell.
[!NOTE] Discogs enforces a 60 requests/minute rate limit. The SDK handles this automatically with exponential backoff and
Retry-Aftersupport — no manual throttling needed.
Fetching resources
# Releases, artists, masters, labels
release = client.releases.get(352665)
print(release.title) # lazy — HTTP fires here → "The Downward Spiral"
artist = client.artists.get(3857)
print(artist.name) # "Nine Inch Nails"
master = client.masters.get(3719)
label = client.labels.get(647)
Search
for result in client.search(query="Pretty Hate Machine", type="release", year="1989"):
print(f"[{result.type}] {result.title}")
# [release] Nine Inch Nails - Pretty Hate Machine
Sub-resources
# Community rating
rating = client.releases.get(352665).rating.get()
print(f"Average: {rating.rating.average}") # Average: 4.49
# Artist releases with sorting
for rel in client.artists.get(3857).releases.list(sort="year", sort_order="desc"):
print(f"{rel.title} ({rel.year})")
# Master versions with filters
for v in client.masters.get(3719).versions.list(format="Vinyl", country="US"):
print(f"{v.title} [{v.format}]")
Async usage
import asyncio
from discogs_sdk import AsyncDiscogs
async def main():
async with AsyncDiscogs() as client: # reads DISCOGS_TOKEN from environment
# Must await lazy resources in async mode
release = await client.releases.get(352665)
print(release.title)
# Async iteration for paginated results
async for result in client.search(query="Nine Inch Nails"):
print(result.title)
asyncio.run(main())
Collection
user = client.users.get("your_username")
# Folders
folders = user.collection.folders.list()
user.collection.folders.create(name="Industrial")
# Browse folder contents
for item in user.collection.folders.get(0).releases.list(sort="added"):
print(item.basic_information.title)
# Add a release
user.collection.folders.get(1).releases.create(release_id=352665)
# Deep chaining: folder -> release -> instance -> fields
user.collection.folders.get(1).releases.get(352665).instances.get(
98765
).fields.update(field_id=1, value="Signed copy")
# Collection value
value = user.collection.value.get()
print(f"Median: {value.median}, Maximum: {value.maximum}")
# Wantlist
user.wantlist.create(release_id=352665, notes="Original pressing", rating=4)
for want in user.wantlist.list():
print(want.basic_information.title)
Marketplace
# Listings
listing = client.marketplace.listings.get(123456789)
new = client.marketplace.listings.create(
release_id=352665, condition="Very Good Plus (VG+)", price=25.00,
)
client.marketplace.listings.update(new.id, price=22.50)
client.marketplace.listings.delete(new.id)
# Orders
for order in client.marketplace.orders.list(status="Payment Received"):
print(f"Order {order.id}: {order.status}")
# Fee lookup
fee = client.marketplace.fee.get(price=25.00, currency="USD")
Error handling
from discogs_sdk import NotFoundError, RateLimitError, AuthenticationError
try:
release = client.releases.get(999999999)
_ = release.title
except NotFoundError:
print("Not found")
except RateLimitError as exc:
print(f"Rate limited, retry after {exc.retry_after}s")
except AuthenticationError:
print("Bad credentials")
The full exception hierarchy:
DiscogsError
├── DiscogsConnectionError
└── DiscogsAPIError
├── AuthenticationError (401)
├── ForbiddenError (403)
├── NotFoundError (404)
├── ValidationError (422)
└── RateLimitError (429)
Examples
The examples/ directory has runnable scripts for every feature:
quickstart.py— first requests, lazy loading, searchauthentication.py— all auth modes including OAuth 1.0adatabase.py— releases, artists, masters, labels, searchmarketplace.py— listings, orders, fees, inventorycollection.py— folders, instances, fields, wantlistasync_usage.py— async client with await and async foradvanced.py— error handling, caching, custom HTTP clients, exports
Configuration
| Parameter | Default | Description |
|---|---|---|
access_token_secret |
None |
OAuth access token secret |
access_token |
None |
OAuth access token |
base_url |
https://api.discogs.com |
API base URL |
cache_dir |
None |
Directory for SQLite cache; in-memory when omitted |
cache_ttl |
3600.0 |
Cache time-to-live in seconds |
cache |
False |
Enable response caching, or pass a custom ResponseCache instance |
consumer_key |
None |
OAuth consumer key |
consumer_secret |
None |
OAuth consumer secret |
http_client |
None |
Custom httpx.Client or httpx.AsyncClient |
max_retries |
3 |
Max retries on 429/5xx/connection errors |
timeout |
30.0 |
Request timeout in seconds |
token |
None |
Personal access token |
Credentials are resolved in order: constructor args > environment variables.
Field naming
Model fields use clean Python names. Where the Discogs API uses inconsistent or cryptic keys, the SDK provides a readable alias while still accepting the raw API name during deserialization:
| API field | Python attribute | Models |
|---|---|---|
anv |
name_variation |
ArtistCredit |
catno |
catalog_number |
LabelCredit, Company, LabelRelease, SearchResult |
created_ts |
created_at |
Export, Upload, List_ |
curr_abbr |
currency_code |
OriginalPrice, User |
curr_id |
currency_id |
OriginalPrice |
extraartists |
extra_artists |
Release, Track |
finished_ts |
finished_at |
Export, Upload |
modified_ts |
modified_at |
List_ |
namevariations |
name_variations |
Artist |
qty |
quantity |
Format |
sublabels |
sub_labels |
Label |
uri150 |
uri_150 |
Image |
Both names work as attributes, so you can use whichever you prefer:
release = client.releases.get(352665) # The Downward Spiral
print(release.extra_artists) # Python name
print(release.extraartists) # API name — same value
Contributing
Contributions are welcome. See CONTRIBUTING.md for guidelines.
License
discogs-sdk is licensed under the Apache License 2.0.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file discogs_sdk-0.3.0.tar.gz.
File metadata
- Download URL: discogs_sdk-0.3.0.tar.gz
- Upload date:
- Size: 33.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
023824f8170ea99cf45622abf66e59f601c79a215e4f03144f10c1f6b43a0f40
|
|
| MD5 |
8635dd59d606834211c4fcb9c5413662
|
|
| BLAKE2b-256 |
6d138d695dcc4f65f7e73004a28848335e1553de380f7499c3fecf9fe9b0e64b
|
Provenance
The following attestation bundles were made for discogs_sdk-0.3.0.tar.gz:
Publisher:
publish.yml on jmfontaine/discogs-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
discogs_sdk-0.3.0.tar.gz -
Subject digest:
023824f8170ea99cf45622abf66e59f601c79a215e4f03144f10c1f6b43a0f40 - Sigstore transparency entry: 983934097
- Sigstore integration time:
-
Permalink:
jmfontaine/discogs-sdk@7d9e29f8633ada01cf237f184bf7b4b485804530 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/jmfontaine
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7d9e29f8633ada01cf237f184bf7b4b485804530 -
Trigger Event:
push
-
Statement type:
File details
Details for the file discogs_sdk-0.3.0-py3-none-any.whl.
File metadata
- Download URL: discogs_sdk-0.3.0-py3-none-any.whl
- Upload date:
- Size: 60.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aa92a305eafe32f02438b2b6058b30384532688ae8e02de09c9108fd6154d5e8
|
|
| MD5 |
52100169f3c7a2bb36d9aa8201ea4923
|
|
| BLAKE2b-256 |
8efdc9201a727f95e07fb1e0c9df91ada4a96a2c25a46a3ee826f95b5f695082
|
Provenance
The following attestation bundles were made for discogs_sdk-0.3.0-py3-none-any.whl:
Publisher:
publish.yml on jmfontaine/discogs-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
discogs_sdk-0.3.0-py3-none-any.whl -
Subject digest:
aa92a305eafe32f02438b2b6058b30384532688ae8e02de09c9108fd6154d5e8 - Sigstore transparency entry: 983934122
- Sigstore integration time:
-
Permalink:
jmfontaine/discogs-sdk@7d9e29f8633ada01cf237f184bf7b4b485804530 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/jmfontaine
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7d9e29f8633ada01cf237f184bf7b4b485804530 -
Trigger Event:
push
-
Statement type: