npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

rekordbox2spotify

v0.1.2

Published

Sync rekordbox playlists to Spotify with multi-stage matching (ID3 ISRC + normalized title/artist + fuzzy)

Readme

rekordbox2spotify

English | 日本語

A CLI tool to sync your rekordbox playlists to Spotify

Recreates and mirrors the playlists you manage in rekordbox on your Spotify account. Whenever you add, remove, or reorder tracks in rekordbox, the next sync propagates those changes to Spotify. Prep your sets in rekordbox, listen on your phone in Spotify — same playlists, same order.

Highlights

  • Multi-stage matching — direct URI → ID3 ISRC tag → normalized title+artist → Levenshtein fuzzy
  • Reads ID3 directly — rekordbox itself doesn't store ISRC, so the tool opens local audio files (MP3/AIFF) and pulls ISRC from ID3 tags to maximize match precision
  • rekordbox is the master — Spotify state is overwritten to match rekordbox. Drop a track in rekordbox and it disappears from Spotify next sync
  • Idempotent — re-runs converge to the same state. If it crashes mid-sync, just run it again
  • Folder hierarchy preserved — rekordbox folders like Genre/Techno become [RB] Genre/Techno in Spotify naming
  • Dry-run mode — preview the plan before any writes
  • Unmatched CSV — tracks Spotify doesn't have are written to a CSV for review

Quickstart

Requirements

  • macOS (other OSes untested)
  • Bun >= 1.1
  • rekordbox 6 or later
  • A Spotify account (free or premium)

1. Install

Via npm (recommended)

bun install -g rekordbox2spotify
mkdir ~/Music/rekordbox-sync && cd ~/Music/rekordbox-sync
rekordbox2spotify init-workspace

From source

git clone https://github.com/ChiakiUehira/rekordbox2spotify.git
cd rekordbox2spotify
bun install

2. Export the rekordbox XML

In rekordbox: File → Library → Export Collection as XML. The default output is ~/Documents/rekordbox.xml.

You can enable automatic export in Preferences → Advanced → Database if you don't want to repeat this every time.

3. Create a Spotify Developer App

  1. Sign in at the Spotify Developer Dashboard
  2. Click Create app
  3. Fill the form:
    • App name: anything (e.g. rekordbox2spotify)
    • App description: anything
    • Redirect URI: http://127.0.0.1:8888/callback (copy verbatim)
    • APIs used: check Web API
  4. Accept terms and Save
  5. Open the created app → Settings and copy the Client ID and Client Secret

4. Configure .env

cp .env.example .env

Edit .env and paste your credentials:

SPOTIFY_CLIENT_ID=your_id_here
SPOTIFY_CLIENT_SECRET=your_secret_here
SPOTIFY_REDIRECT_URI=http://127.0.0.1:8888/callback

5. Authenticate

bun run rekordbox2spotify init

Your browser opens the Spotify consent screen. Log in, approve, and the token is saved to .cache/spotify_token.json.

6. Sync

Preview first:

bun run rekordbox2spotify sync --xml ~/Documents/rekordbox.xml --dry-run

When the plan looks right, run for real:

bun run rekordbox2spotify sync --xml ~/Documents/rekordbox.xml

Playlists named [RB] {playlist_name} appear in your Spotify account.


Command reference

init — Spotify OAuth

bun run rekordbox2spotify init

Only needed once. A refresh token is stored at .cache/spotify_token.json and reused on subsequent runs.

sync — run sync

bun run rekordbox2spotify sync --xml <path> [--dry-run] [--out-dir <dir>]

| Option | Description | |---|---| | --xml <path> | Path to rekordbox XML (falls back to config.yaml, then default paths) | | --dry-run | Print the plan without writing | | --out-dir <dir> | Where to write logs (default ./logs) |

verify — diagnose the XML

bun run rekordbox2spotify verify --xml <path>

Reports what metadata is available in the rekordbox XML — ISRC coverage, intelligent playlist suspects, folder structure, etc.

unmatched — review unmatched tracks

bun run rekordbox2spotify unmatched

Prints the most recent unmatched-track list. The CSV is also at ./logs/unmatched_*.csv.


Configuration (config.yaml)

Copy config.example.yaml:

rekordbox:
  source: xml
  xml_path: ~/Documents/rekordbox.xml
  # Exact-match playlist names to exclude from sync
  ignore_playlists:
    - "Trial playlist - Cloud Library Sync"
    - "CUE解析用プレイリスト"

spotify:
  playlist_prefix: "[RB] "
  folder_separator: "/"
  visibility: private

matching:
  fuzzy_threshold: 0.75       # 0.0–1.0, lower is more permissive (higher false-match risk)
  duration_tolerance_ms: 3000
  prefer_original_mix: true   # prefer candidates whose title contains "Original Mix"

output:
  log_dir: ./logs
  cache_dir: ./.cache

Sync behavior

| rekordbox change | What happens on Spotify next sync | |---|---| | Track added | Added to the playlist | | Track removed | Removed from the playlist | | Track reordered | Order is mirrored | | Playlist deleted | Unfollowed on Spotify (the playlist itself still exists on Spotify's servers but disappears from your library) | | Playlist renamed | Old name is unfollowed, new name is created | | You edit a playlist directly on Spotify | Overwritten on next sync — rekordbox is the master |

Each playlist's description is set to Last synced: YYYY-MM-DD HH:MM JST on every run, so you can see when it was last synced.


Matching strategy

For each track, strategies are tried in order; the first hit wins:

| # | Strategy | What it does | Confidence | |---:|---|---|---:| | 1 | Direct URI | rekordbox Location is spotify:track:XXX (Spotify-linked track) | 1.00 | | 2 | ISRC | Read ID3 tag from the local audio file → Spotify isrc search | 0.95 | | 3 | Normalized exact | Normalize title/artist (strip (Original Mix), feat., (GB), etc.) and look for an exact match | 0.85 | | 4 | Fuzzy | Levenshtein similarity, pick the highest above threshold | 0.75–0.99 | | 5 | Duration tiebreaker | When candidates tie, prefer ones within ±3 s of target duration, plus prefer_original_mix | — |

Tracks that fail all strategies end up in logs/unmatched_*.csv.

Normalization rules

Strips title suffixes, feat./ft./featuring clauses, trailing (GB)/(IT) country codes on artists:

| Input | Normalized | |---|---| | Echoes (Original Mix) | echoes | | Track feat. Someone (Extended Mix) | track | | FLETCH (GB) | fletch | | Echoes (full-width) | echoes |


Known limitations

Spotify Web API constraints

  • No folder API — Spotify doesn't expose playlist folders through the Web API. Hierarchy is only expressed in the playlist name (e.g. [RB] Genre/Techno). Use the Spotify app to organize them into folders manually
  • No truly private playlists — even with public: false, anyone with the URL can access the playlist (Spotify's design)

rekordbox constraints

  • rekordbox doesn't store ISRC — neither in the UI nor in the XML export. This tool reads ID3 tags from the underlying audio files to recover ISRC
  • master.db is SQLCipher-encrypted — rekordbox 6+ databases are not readable by this tool. XML export is required

Tracks not on Spotify

Bandcamp exclusives, self-released dubs, label-only edits, old bootlegs, etc. simply aren't on Spotify and will land in unmatched. Check logs/unmatched_*.csv to review them.


Troubleshooting

Spotify トークン未取得です / "Spotify token missing"

Run:

bun run rekordbox2spotify init

You either haven't authenticated yet or need to re-auth.

Low match rate

  1. Lower matching.fuzzy_threshold in config.yaml (default 0.75 → 0.65). Increases false-match risk
  2. Run unmatched and inspect: if most are Bandcamp, there's nothing to do; if many are naming-variant misses, lowering the threshold may help

[RB] playlists show as Public

Disable Settings → Social → Automatic new playlists are public in the Spotify app. With it on, Spotify overrides public: false from the API.

Nothing happens with --dry-run

That's normal. --dry-run only prints the plan. Remove the flag to actually write:

bun run rekordbox2spotify sync --xml ~/Documents/rekordbox.xml

For developers

Local dev

bun install
bun test            # run all tests
bun run typecheck   # type check

Architecture

src/
├── cli.ts                  # commander entrypoint
├── verify.ts               # XML diagnosis
├── sync.ts                 # sync orchestration
├── readers/
│   ├── xml.ts              # rekordbox XML parser
│   ├── db-probe.ts         # master.db diagnostic
│   └── id3.ts              # ID3 tag → ISRC extractor
├── spotify/
│   ├── auth.ts             # OAuth + token management
│   ├── client.ts           # API client (rate limit + retry)
│   └── playlist.ts         # playlist CRUD
├── matcher/
│   ├── normalize.ts        # string normalization
│   ├── strategies.ts       # individual matching strategies
│   └── index.ts            # multi-stage orchestration
├── unmatched.ts            # CSV I/O
├── report.ts               # verify report rendering
└── types.ts                # shared types

Design docs

Contributing

Issues and PRs welcome. Bug reports and feature requests go to GitHub Issues.


License

MIT License