skip to content

beets Music Organizer

Importing, tagging, querying, and organizing a music library with beets — config, plugins, queries, and common workflows on Windows.

10 min read 73 snippets

beets Music Organizer#

What it is#

beets is a free, open-source command-line music library manager written in Python and maintained at beets.io. It auto-tags audio files by matching them against the MusicBrainz database, renames and moves them into a configurable folder structure, and exposes a powerful query language for searching, filtering, and reporting on your collection. Reach for beets when you want fully automated, metadata-accurate music organization from the terminal, with a plugin ecosystem covering art fetching, lyrics, acoustic fingerprinting, and more.

What’s new in 2026#

beets is in active development — three minor releases shipped between April and May 2026 (current line is v2.11.x, see the release page for exact numbers):

  • Python 3.14 is now officially supported (added in v2.9.0).
  • A new Tidal plugin fetches metadata directly from Tidal alongside MusicBrainz (v2.11.0).
  • The fetchart plugin now accepts WebP album art.
  • Portable library paths — beets can store paths relative to the library root, so your DB survives moving the library between drives or platforms (v2.10.0).
  • The web plugin patched a stored-XSS vulnerability in unescaped metadata fields. Upgrade beets[web] if you expose the built-in HTTP server.
  • The smartplaylist plugin gained a dest_regen option to rewrite item paths when generating playlists, and splupdate output was restructured.
  • beet import can now fall back to ffprobe to detect the format of extensionless input files instead of skipping them.

Upgrade in place: pip install -U beets (or pipx upgrade beets if you installed with pipx — the recommended path on modern Windows).

Install#

Via pip (Python 3.8+):

pip install beets

Install with common optional dependencies in one shot:

pip install beets requests pylast pyacoustid chromaprint

Verify:

beet --version

Output:

beets version 2.0.0
Python version 3.12.3

Configuration file#

beets reads %APPDATA%\beets\config.yaml on Windows.

Open or create it:

beet config -e

Minimal working config:

# %APPDATA%\beets\config.yaml
directory: ~/Music/Library
library: ~/Music/beets.db

import:
  move: yes         # move files into directory (use copy: yes to keep originals)
  write: yes        # write tags to files after importing
  log: ~/Music/import.log

ui:
  color: yes

plugins:
  - fetchart
  - embedart
  - lyrics
  - lastgenre
  - duplicates
  - missing
  - info
  - edit

Path format (how files are organized under directory):

paths:
  default: $albumartist/$year - $album%auniq{}/$track - $title
  singleton: Non-Album/$artist - $title
  comp: Compilations/$year - $album%auniq{}/$track - $title

Import music#

Import a folder — beets looks up tags on MusicBrainz interactively:

beet import "C:\Users\Jay\Downloads\NewMusic"

Output (interactive):

Tagging:
    The Beatles / Abbey Road
URL:      https://musicbrainz.org/release/d6dc93a4-b294-4dc8-8d7c-f430c9bd09bc
(Similarity: 99.5%) (Tracks: 17, Score: 100%)
 * 01 Come Together        -> 01 Come Together
 * 02 Something            -> 02 Something
...
Apply, More candidates, Skip, Use as-is, as Tracks, Group albums,
Enter search, enter Id, aBort? [A]

Import without asking (auto-select best match):

beet import -A "C:\Users\Jay\Downloads\NewMusic"

Import and copy files instead of moving:

beet import -c "C:\Users\Jay\Downloads\NewMusic"

Import a single file as a singleton (not part of an album):

beet import -s "C:\Users\Jay\Downloads\song.mp3"

Re-import existing library items (re-tag from MusicBrainz):

beet import -L

Import without writing any tags (just add to database):

beet import -W "C:\Path\To\Music"

Query the library#

List everything:

beet list

Output:

The Beatles - Abbey Road - Come Together
The Beatles - Abbey Road - Something
Radiohead - OK Computer - Paranoid Android
Radiohead - OK Computer - Karma Police
...

Search by artist:

beet list artist:radiohead

Search by album:

beet list album:"ok computer"

Search by year range:

beet list year:1990..2000

Search by genre:

beet list genre:jazz

Multiple conditions (AND by default):

beet list artist:beatles year:1969

Regex match:

beet list "title::^(Come|Something)"

Items without album art:

beet list -a artworks:0

List albums (one line per album):

beet list -a artist:radiohead

Output:

Radiohead - The Bends (1995)
Radiohead - OK Computer (1997)
Radiohead - Kid A (2000)
Radiohead - Amnesiac (2001)

Print specific fields:

beet list -f '$artist - $album ($year)' artist:beatles

Output:

The Beatles - Please Please Me (1963)
The Beatles - With the Beatles (1963)
The Beatles - A Hard Day's Night (1964)

Count results:

beet list artist:beatles | Measure-Object -Line

Modify tags#

Change a field on matching items:

beet modify artist:"The Beatles" genre="Classic Rock"

Fix a wrong year on an album:

beet modify -a album:"Abbey Road" year=1969

Clear a field:

beet modify title:"Bad Title" title=""

Open items in an interactive editor (requires edit plugin):

beet edit artist:radiohead

Update & move files#

Re-tag and move files to match current config paths:

beet move artist:radiohead

Move everything (reorganize after a path format change):

beet move

Re-write tags to disk without moving:

beet write artist:beatles

Update the database after manually editing tags outside beets:

beet update

Remove items#

Remove a track from the library (database only, keeps the file):

beet remove title:"Come Together"

Remove and delete the file from disk:

beet remove -d title:"Come Together"

Remove an entire album:

beet remove -a album:"Abbey Road"

Plugins#

Enable plugins in config.yaml under the plugins: key, then configure each below it.

fetchart — download album artwork#

Automatically downloads cover art from sources like iTunes, Amazon, and Last.fm and saves it as a cover.jpg alongside the album files. Run beet fetchart at any time to fill in art for albums that were imported without it.

plugins:
  - fetchart

fetchart:
  auto: yes
  minwidth: 500
  quality: 90
  sources: filesystem coverart itunes amazon lastfm wikipedia

Fetch art for items that are missing it:

beet fetchart

Force re-fetch all art:

beet fetchart -f

embedart — embed art into audio files#

Reads the cover art file from the album folder (fetched by fetchart) and writes it into each audio file’s metadata tags so it is visible in all players, not just those that read folder art. Use both fetchart and embedart together for full coverage.

plugins:
  - embedart

embedart:
  auto: yes
  compare_threshold: 100

Embed art from the folder into all files in the library:

beet embedart

lyrics — fetch and store lyrics#

Searches Genius, Musixmatch, and other sources for song lyrics and stores them in the lyrics field of the beets database (and optionally the file tags). Useful for offline lyric display in players that read embedded tags.

plugins:
  - lyrics

lyrics:
  auto: yes
  fallback: ""
  sources: genius musixmatch tekstowo

Fetch lyrics for everything:

beet lyrics

Fetch lyrics for a specific artist:

beet lyrics artist:radiohead

lastgenre — set genre from Last.fm tags#

Queries the Last.fm API for crowd-sourced genre tags associated with the artist or album and writes the best match into the genre field. More accurate than MusicBrainz genre data for popular music; requires the pylast package.

plugins:
  - lastgenre

lastgenre:
  auto: yes
  count: 1
  prefer_specific: yes
  source: album

Apply genres to untagged items:

beet lastgenre

duplicates — find duplicate tracks#

Identifies tracks that share the same artist and title (or a configurable fingerprint) across the library, reporting both copies so you can decide which to keep. Useful after merging two collections or after re-importing files that were already present.

plugins:
  - duplicates

List duplicates (same artist + title):

beet duplicates

Output:

The Beatles - Abbey Road - Come Together  [/Music/Library/...]
The Beatles - Abbey Road - Come Together  [/Music/Inbox/...]

Delete duplicate copies (keeps first found):

beet duplicates -d

missing — find incomplete albums#

Compares the number of tracks you have for each album against the MusicBrainz total track count and reports albums where tracks are missing. Useful for auditing a library and prioritizing what to source.

plugins:
  - missing

Show albums with fewer tracks than MusicBrainz reports:

beet missing

Output:

The Beatles - Abbey Road (17/17) — OK
Radiohead - OK Computer (12/12) — OK
Pink Floyd - The Wall (26/26) — OK
Radiohead - The Bends (12/12) — OK

acousticbrainz / bpd — BPM and key detection#

bpd turns beets into a lightweight MPD-compatible music server, letting any MPD client (ncmpcpp, Cantata, etc.) browse and play the beets library. Use it when you want library-aware playback without exporting playlists.

plugins:
  - bpd

Play music from the library via MPD protocol (requires an MPD client):

beet bpd

info — inspect a file’s tags#

Prints all metadata fields beets reads from a file — both embedded tags and beets database fields — without modifying anything. Use it to diagnose why a track is tagged incorrectly or to verify that embedart wrote the expected fields.

plugins:
  - info

Show all tags for a file:

beet info "C:\Music\song.mp3"

Output:

albumartist: The Beatles
album:       Abbey Road
title:       Come Together
track:       1
tracktotal:  17
year:        1969
genre:       Rock
mb_albumid:  d6dc93a4-b294-4dc8-8d7c-f430c9bd09bc
mb_trackid:  84c8f3da-a0a2-4573-8dc4-fae33f00e92e

Statistics & reporting#

Count items in the library:

beet stats

Output:

Tracks: 4,312
Total time: 12.2 days
Approximate total size: 38.41 GB
Artists: 283
Albums: 521
Album artists: 217

List all artists:

beet list -a | ForEach-Object { $_ -replace " - .*", "" } | Sort-Object -Unique

Albums sorted by year:

beet list -a -f '$year $albumartist - $album' | Sort-Object

Scripting with beet#

Export library as JSON (useful for external tooling):

beet ls -f json > library.json

Print all file paths (for piping to other tools):

beet list -p

Output:

C:\Users\Jay\Music\Library\The Beatles\1969 - Abbey Road\01 - Come Together.flac
C:\Users\Jay\Music\Library\The Beatles\1969 - Abbey Road\02 - Something.flac
...

Pipe paths to foobar2000 or any player:

beet list -p artist:radiohead | Out-File -Encoding UTF8 playlist.m3u

Full config.yaml reference#

directory: ~/Music/Library
library: ~/Music/beets.db

import:
  move: yes
  write: yes
  log: ~/Music/import.log
  autotag: yes
  timid: no          # set yes to confirm every import even with high-confidence match

match:
  strong_rec_thresh: 0.10   # auto-accept matches below this distance
  medium_rec_thresh: 0.25
  max_rec:
    missing_tracks: medium
    unmatched_tracks: medium

paths:
  default: $albumartist/$year - $album%auniq{}/$track - $title
  singleton: Non-Album/$artist - $title
  comp: Compilations/$year - $album%auniq{}/$track - $title

ui:
  color: yes

plugins:
  - fetchart
  - embedart
  - lyrics
  - lastgenre
  - duplicates
  - missing
  - info
  - edit

fetchart:
  auto: yes
  minwidth: 500
  sources: filesystem coverart itunes amazon lastfm

embedart:
  auto: yes

lyrics:
  auto: yes
  sources: genius musixmatch

lastgenre:
  auto: yes
  count: 1
  prefer_specific: yes

Common workflows#

First-time library setup#

# 1. Edit config
beet config -e

# 2. Import entire music folder
beet import "C:\Users\Jay\Music\Inbox"

# 3. Fetch missing art
beet fetchart

# 4. Embed art into files
beet embedart

# 5. Tag genres
beet lastgenre

# 6. Fetch lyrics
beet lyrics

# 7. Check for duplicates
beet duplicates

Add new downloads#

# Download with yt-dlp, then import
yt-dlp -x --audio-format flac -o "C:\Music\Inbox\%(uploader)s - %(title)s.%(ext)s" "URL"
beet import -A "C:\Music\Inbox"

Fix bad tags before import#

Open the file in the interactive editor before beets touches it:

beet import "C:\Music\Inbox\album"
# When prompted, choose 'e' to edit candidates, or 'i' to enter a MusicBrainz ID manually

Troubleshooting#

ProblemFix
No candidates foundRun beet import without -A, choose Enter search or enter Id to supply a MusicBrainz ID manually
Files not movingCheck import: move: yes in config; also verify beets has write permission to directory
Art not embeddingEnable both fetchart and embedart; run beet fetchart then beet embedart
Duplicate entries after re-importRun beet duplicates -d to clean up; then beet update
Config not foundRun beet config -p to see the expected path
Unicode filenames brokenEnsure terminal is UTF-8; add PYTHONUTF8=1 to your environment variables

Sources#