This release is a pre-release and may not be stable for production use.
pymetal
A Python client for Encyclopaedia Metallum (the Metal Archives). It uses a relational data model that keeps facts flat scrapers usually lose: splits, lineups that change over time, and tracks reused across releases.
Built on curl_cffi for TLS-fingerprint bypass and pydantic for typed, validated data.
Why
Most scrapers model Track = (id, title, band, album). That model collapses three facts that MA keeps separate.
- A track can have multiple bands (split releases, collaborations).
- A band's lineup is time-sliced. The same band on two tracks can mean different people.
- A track can appear on many releases (compilations, re-issues, singles).
pymetal models each fact as a separate entity (TrackAppearance, LineupMember, ReleaseLineup), keyed by metal-archives ids. This keeps re-scrapes idempotent.
Install
pip install -e .
Requires Python 3.10+. Pulls in curl_cffi, lxml, pydantic>=2, and random-user-agent.
Quick start
from pymetal import MetalArchives
ma = MetalArchives()
# Search bands with the full advanced-search filter set.
for hit in ma.search_bands(country="PT", genre="Heavy", year_from=1980, year_to=1989):
print(hit.ma_id, hit.name, hit.country)
# Pull a release with all its tracks (per-band attribution on splits).
release, songs, appearances = ma.get_release(451600) # Carcass — Heartwork
print(release.cover_url, release.total_length, release.label_name)
print(release.reviews_count, "reviews", release.reviews_avg_percent, "% avg")
# Lineup over time — Current / Past / Live / Last-known / Guest-Session.
for member in ma.get_lineup(14):
print(member.status, member.artist_name, member.role, member.date_from, member.date_to)
# Lyrics by song id.
print(ma.get_lyrics_by_song_id(172090))
More examples are in examples/:
metalarchives.py: a full API tourbrowse.py: catalog walks (country, genre, letter, labels, reviews, upcoming, RIP)portuguese_heavy_metal_pre2000.py: a resumable lyrics-corpus crawlmetallvm-rest.py: a FastAPI server that exposes every endpoint over HTTP
Endpoints
Search (advanced-search forms)
| Function | What it returns |
|---|---|
search_bands(...) |
Iterator[BandSearchHit]. Covers every advanced filter: country, status, year range, themes, location, label. |
search_albums(...) |
Iterator[AlbumSearchHit]. Covers release type, format, label, catalog/barcode, year and month range. |
search_songs(...) |
Iterator[SongSearchHit]. Full-text lyrics search, carries band_id, release_id, and lyrics_id. |
Detail pages
| Function | What it returns |
|---|---|
get_band(id) |
Band: name, country, genres, themes, labels, comment, photo, audit. |
get_lineup(id) |
List[LineupMember], partitioned by status with role-date ranges. |
get_release(id) |
(Release, List[Song], List[TrackAppearance]). Splits attribute tracks per band. |
get_release_lineup(id) |
List[ReleaseLineup]: band, guest, and staff credits. |
get_other_versions(id) |
List[Release]: re-issues, re-masters, regional editions. |
get_discography(id) |
List[Release] |
get_artist(id) |
Artist: real name, born, R.I.P., died of, place of birth. |
get_label(id) |
Label: address, phone, styles, founding date, sub-labels, parent. |
get_band_recommendations(id) |
List[BandRecommendation], MA's "Similar artists" tab. |
get_band_reviews(id) |
Iterator[Review], every user review of every release by a band. |
get_links(id, entity_type='band') |
List[ExternalLink]: Bandcamp, Spotify, and merch links grouped by section. |
get_lyrics_by_song_id(id) |
Optional[str] |
get_lyrics(...) |
Iterator[str], a combined search and lyrics fetch. |
Catalog browse and discovery
| Function | What it returns |
|---|---|
browse_bands_by_country(code) |
Iterator[BandSearchHit], the full country listing. |
browse_bands_by_genre(slug) |
Iterator[BandSearchHit], from a 23-bucket coarse taxonomy. |
browse_bands_by_letter(letter) |
Iterator[BandSearchHit], alphabetical (A-Z, NBR, ~). |
browse_labels_by_country(code) |
Iterator[Label] |
browse_labels_by_letter(letter) |
Iterator[Label] |
browse_reviews(year, month) |
Iterator[Review], reviews posted in a given month. |
get_upcoming_releases() |
Iterator[UpcomingRelease], scheduled future releases. |
get_rip_artists() |
Iterator[RIPArtist], MA's deceased-artists list. |
list_countries() |
dict[code, name], all MA-known country codes. |
list_genre_slugs() |
list[str], the 23 genre browse slugs. |
All functions return Pydantic v2 models. .model_dump_json() round-trips on every type.
Documentation
- Getting Started: install and first commands.
- API Reference: every public class and method.
- Advanced Usage: splits, lineups over time, pagination, caching, lyrics download.
- Developer Guide: adding endpoints, capturing fixtures, running tests.
License
Apache 2.0
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 pymetal-1.1.0a2.tar.gz.
File metadata
- Download URL: pymetal-1.1.0a2.tar.gz
- Upload date:
- Size: 40.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34a6ab9111e3eb9ba12918ca7d41dc35b11cc03df05dae923bada37c9f201bd3
|
|
| MD5 |
0940e46834b87559140fc0e0d72eb6e8
|
|
| BLAKE2b-256 |
2fd530f9fe663107d6fc3fe860421f538b89ddc7e8702440d448358a9368217a
|
File details
Details for the file pymetal-1.1.0a2-py3-none-any.whl.
File metadata
- Download URL: pymetal-1.1.0a2-py3-none-any.whl
- Upload date:
- Size: 33.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b8602627d62cc8a0fdd61b46bd2a33e39a10f1962cac7eb5733aa18a752016d5
|
|
| MD5 |
e3c50c54ca169bef6bde4d72ef876f80
|
|
| BLAKE2b-256 |
a4b5d7e5bf55dfc1ba5a9c1f5dbb99a3cbf71456002084aeeb0ea95ac2a9d9cc
|