Darek Kay's picture Darek Kay

Reverse-engineering the Foobar2000 index file format

I've been using Foobar2000 as my music player for over a decade. On mobile, I've switched to Plex, after Google shut down yet another service (Google Music). It's always been a hassle to keep my playlists in sync, so I finally wrote a Foobar2000 → Plex synchronization tool.

One of the challenges was to extract the Foobar2000 playlist data that is stored in a binary index.dat file. As the file format description is not publicly available, I had to reverse-engineer it myself. 🕵️‍♂️

Debugging process

Opening the binary index.dat file in a text editor doesn't make much sense. You can spot some plain-text data (e.g. "Library" = playlist name), but the rest is gibberish. That's because most of the data needs to be interpreted differently than a byte to char conversion.

Text editor displaying mostly incomprehensible characters

Foobar2000 is closed-source, so there's only limited information available about its internals. There's an unofficial documentation, but it only describes the playlist format, not the index.dat file. It was useful nonetheless, as it brings up two concepts:

  • A fixed-length "magic signature" header that can be skipped
  • Prepending the number of bytes of variable-length data

Both principles apply to the index.dat file as well. Let's open this file with a hex viewer:

Hex representation of the index.dat file

  • The first line doesn't contain any meaningful data and can be skipped.
  • Do you notice the 07 00 00 00 byte sequence right before "Library"? It is the hexadecimal number of bytes that the following field takes up ("Library" = 7 bytes / characters). This principle is used throughout the file for storing all the variable-length playlist data.

File format

For people interested in the actual format description, here is my final result.

Here are the first 24 bytes of data:

  • 16 bytes: File header (a)
  • 4 bytes: Number of playlists (b)
  • 4 bytes: Unknown

File header byte structure

Then, the following structure repeats itself for every playlist:

  • 4 bytes: Playlist name length x (c)
  • x bytes: Playlist name (d)
  • 4 bytes: Unknown
  • 2 bytes: Playlist metadata length y (e)
  • y bytes: Playlist metadata (f)
  • 2 bytes: Unknown
  • 4 bytes: Number of playlist files z (g)
  • z times 16 bytes: Playlist file names (16 bytes per file name) (h)

Playlist data byte structure

Some final notes:

  • If a playlist doesn't contain any tracks, there is no respective playlist file.
  • Foobar2000 splits large playlists into multiple files.

Want to leave a comment?

If you want to give me some feedback, please contact me via Twitter or email. 💌

Reverse-engineering the Foobar2000 index file format