Extract BandCamp .zip album folders to their appropriate place
Project description
Band Camp Album Extractor
This python script extracts all of the songs for a bandcamp album download.
Install
(preferred) from pip
pip install bandcamp_extract
From github repo
To install this package simply run
pip install .
in the root of this package
Setup
After installation the extractor's binary is called bcextr.
Breaking change (0.2.0):
bcextris now a command group. What used to bebcextr <zip>is nowbcextr extract <zip>.
bcextr extract works standalone with no setup. The bcextr api commands
pull albums directly from your Bandcamp collection, which requires a one-time
login first.
Bandcamp has no username/password API, so this reuses the same session cookie your browser already has after you log in on bandcamp.com.
1. Get your Bandcamp username
This is the name in the URL of your own collection page:
https://bandcamp.com/<username>. You can find it in the account menu on
bandcamp.com, or from the URL after clicking "Collection".
2. Get your identity cookie
- Log in to bandcamp.com in your browser.
- Open developer tools (
F12, orCmd+Opt+Ion macOS). - Go to the Application tab in Chrome/Edge (Storage tab in Firefox),
then Cookies →
https://bandcamp.comin the left sidebar. - Find the row named
identityand copy its Value column. It's a long opaque string — copy the whole thing.
This cookie is a live login credential for your account: don't share it,
paste it into chat tools, or commit it anywhere. bcextr only stores it
locally in ~/.config/bcextr/session.json (readable only by you).
3. Log in with bcextr
bcextr api login
You'll be prompted for your Bandcamp username and the cookie value from the steps above.
If your cookie later expires, just re-run bcextr api login with a fresh
value.
Shell completion (optional)
bcextr is built on Click, which
provides tab-completion for subcommands (extract, api, mv, etc.) and
file/directory paths (including for --pattern, which completes like a
regular folder path). Add the line for your shell to its startup file, then
restart your shell (or source the file):
bash (~/.bashrc):
eval "$(_BCEXTR_COMPLETE=bash_source bcextr)"
zsh (~/.zshrc):
eval "$(_BCEXTR_COMPLETE=zsh_source bcextr)"
fish: generate the completion file once (no eval-on-startup needed):
_BCEXTR_COMPLETE=fish_source bcextr > ~/.config/fish/completions/bcextr.fish
Usage
bcextr extract
Extract a zip you already downloaded:
bcextr extract ~/Downloads/album.zip --pattern ~/Music/{artist}/{album}/{title}
Default pattern if not provided is: ./{artist}/{album}/{title}
bcextr api list / bcextr api choose
List your collection:
bcextr api list
Pick albums and extract them straight to your library:
bcextr api choose --pattern ~/Music/{albumartist}/{album}/{title} --format flac
This opens an fzf multi-select over your collection, downloads each chosen
album in the requested format, and runs it through the same extract/rename
logic as bcextr extract.
--format accepts one of mp3-320, mp3-v0, flac, aac-hi, vorbis,
alac, wav, aiff-lossless. If omitted, you'll get a format picker
(applied to the whole batch) instead.
This relies on Bandcamp's unofficial, undocumented collection API and may break if Bandcamp changes it.
bcextr mv / bcextr cp
Reorganize an existing folder of music (searched recursively, however deep the
files are nested) into a pattern-based structure. mv moves the files (the
originals are gone); cp copies them, leaving the originals in place:
bcextr mv ~/Music --pattern ~/New_Music/{albumartist}/{album}/{title}
bcextr cp ~/Music --pattern ~/New_Music/{albumartist}/{album}/{title}
Pattern substitution
The pattern substitution will substitute any parameter it gets in tinytag
The file extension will also be added to the end of the pattern when moving
the song to it's destination
tag.album # album as string
tag.albumartist # album artist as string
tag.artist # artist name as string
tag.audio_offset # number of bytes before audio data begins
tag.bitrate # bitrate in kBits/s
tag.comment # file comment as string
tag.composer # composer as string
tag.disc # disc number
tag.disc_total # the total number of discs
tag.duration # duration of the song in seconds
tag.filesize # file size in bytes
tag.genre # genre as string
tag.samplerate # samples per second
tag.title # title of the song
tag.track # track number as string
tag.track_total # total number of tracks as string
tag.year # year or data as string
It is important to note that any files that are not music (in the zip, or in the
source folder for bcextr mv/bcextr cp) are not moved or copied to the
destination folder.
Path-unsafe symbols in metadata
Before substitution, every metadata value is run through
pathvalidate's replace_symbol to
strip characters that would otherwise break the destination path (e.g. /,
:, ?). By default these are removed entirely; pass --replacement-text to
substitute something else instead:
bcextr extract ~/Downloads/album.zip --pattern ~/Music/{artist}/{album}/{title} --replacement-text "_"
Project details
Release history Release notifications | RSS feed
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 bandcamp_extract-0.4.1.tar.gz.
File metadata
- Download URL: bandcamp_extract-0.4.1.tar.gz
- Upload date:
- Size: 11.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5e38639f2076e9a3c2762c7877bf12497745998703eb4b0f779e1b10ddcc9a69
|
|
| MD5 |
8a71a6ea6cf1b1d47fc0e3c7cabf5457
|
|
| BLAKE2b-256 |
e5df30afa9d6dd299ff7c19ab3cbbfa65cb01574c1ea749816eca57b9908f30a
|
Provenance
The following attestation bundles were made for bandcamp_extract-0.4.1.tar.gz:
Publisher:
release.yml on JonMontgo/bandcamp_extract
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bandcamp_extract-0.4.1.tar.gz -
Subject digest:
5e38639f2076e9a3c2762c7877bf12497745998703eb4b0f779e1b10ddcc9a69 - Sigstore transparency entry: 2131399433
- Sigstore integration time:
-
Permalink:
JonMontgo/bandcamp_extract@c8428f7fad6d4c88cd7dfd9609762ee61007c39f -
Branch / Tag:
refs/heads/master - Owner: https://github.com/JonMontgo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c8428f7fad6d4c88cd7dfd9609762ee61007c39f -
Trigger Event:
push
-
Statement type:
File details
Details for the file bandcamp_extract-0.4.1-py3-none-any.whl.
File metadata
- Download URL: bandcamp_extract-0.4.1-py3-none-any.whl
- Upload date:
- Size: 12.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c635b73d60894f13b2244cff8b3045ffe5ddded926f7324012c1d0c40a9ab650
|
|
| MD5 |
379c07507822f7f37d8233ce8ec8bd42
|
|
| BLAKE2b-256 |
7b16c8882a3fa8c6329570d85d52270958c2ca0d6a5e8f7ba3ea8f9b3a24646a
|
Provenance
The following attestation bundles were made for bandcamp_extract-0.4.1-py3-none-any.whl:
Publisher:
release.yml on JonMontgo/bandcamp_extract
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bandcamp_extract-0.4.1-py3-none-any.whl -
Subject digest:
c635b73d60894f13b2244cff8b3045ffe5ddded926f7324012c1d0c40a9ab650 - Sigstore transparency entry: 2131399702
- Sigstore integration time:
-
Permalink:
JonMontgo/bandcamp_extract@c8428f7fad6d4c88cd7dfd9609762ee61007c39f -
Branch / Tag:
refs/heads/master - Owner: https://github.com/JonMontgo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c8428f7fad6d4c88cd7dfd9609762ee61007c39f -
Trigger Event:
push
-
Statement type: