There is a particular kind of quiet rebellion happening on laptops and single-board computers around the world. It does not make headlines. It does not have a marketing budget. It rarely trends. But if you follow the trail of self-hosted servers humming in closets, of Git repositories with names like Feishin and Amperfy and Supersonic, of forum threads where strangers swap tips about gapless playback and transcoding bitrates, you will find a thriving, stubborn, generous culture: independent developers building music players that talk to a common protocol called the Subsonic API, so that ordinary people can keep owning the music they love.
This is a story about craft as much as code. It is about why someone with a full-time job and a family would spend their weekends writing a media client that maybe a few thousand people will ever install. It is about an open API that quietly became the connective tissue of an entire ecosystem, and about a community-driven revival — OpenSubsonic — that dragged that API into the modern era. And underneath all of it, it is about a simple, almost old-fashioned idea: that the songs you have collected over a lifetime should belong to you, and that no company should be able to take them away by changing a licensing deal or shutting down a service.
Let us start at the beginning, from code, and end where the music actually plays — on stage, in your ears, in the room.
The server that started it all
Subsonic began as a personal media streaming server. The premise was modest and, in hindsight, prophetic: you have a folder of music files sitting on a computer at home, and you would like to listen to them from anywhere — your phone on the bus, your laptop at the office, a browser at a friend’s house — without uploading everything to a third party. Subsonic scanned your library, read the tags, organized artists and albums, and exposed all of it over the network. Crucially, it also published a REST API so that other programs could talk to it.
That decision — to open the API — is the seed from which everything else grew. The original Subsonic software eventually moved toward a more restricted, premium model, and its licensing became a point of friction for parts of the community. But the API had already escaped into the world. Because it was documented and stable, developers could write their own clients against it, and server authors could write their own servers that spoke the same language. The protocol outlived the politics.
Two things then happened that shaped the modern landscape. First, forks and independent servers appeared. Airsonic, and later Airsonic-Advanced, emerged as open-source continuations in the same lineage. Then a new generation of servers arrived built from scratch but deliberately speaking the Subsonic dialect. The most prominent of these is Navidrome, a lightweight, fast, self-hosted music server written in Go that has become something of a default recommendation in self-hosting communities. Others include Gonic, another lean Go server; Ampache, a long-running PHP music application that added Subsonic API support; the Lightweight Music Server (LMS); Supysonic; Nextcloud Music; and partial or adjacent support in projects like Funkwhale. Each of these is a different codebase with different priorities, but they share one thing: a client written for one can, to a large degree, talk to all of them.
That is the quiet magic of a shared protocol. The server and the client no longer have to come from the same vendor. A person can run Navidrome on a Raspberry Pi and choose, from dozens of independently built apps, whichever player best suits their phone, their taste, and their ears. This is the opposite of the walled garden. It is a garden with the walls knocked down and the gates propped open.
What the API actually offers a developer
To understand why so many people build clients, it helps to understand what the API hands them for free. The Subsonic API is, at its heart, a set of HTTP endpoints that return structured data (originally XML, and in modern usage typically JSON). A developer does not have to solve the hard problems of scanning files, reading ID3 tags, maintaining a database, or transcoding audio. The server does all of that. The client just asks questions and plays results.
The endpoints fall into a handful of intuitive categories:
- Browsing the library. Calls like
getMusicFolders,getIndexes,getArtists,getAlbumList, andgetAlbumlet a client walk the structure of a collection — from top-level folders down to artists, albums, and individual tracks. There is both a folder-based view and a tag-based (ID3) view, so a client can present music the way its users think about it. - Searching.
search3and related endpoints let a user type a few letters and get back matching artists, albums, and songs. For a client developer, full-text search over the whole library is essentially a single request. - Streaming and downloading.
streamdelivers the actual audio, optionally transcoded on the fly to a different format or bitrate, which is enormously useful on a phone with a weak connection.downloadfetches the untouched original file.getCoverArtreturns album artwork, with optional resizing so a client can request a thumbnail instead of a full-resolution image. - Playlists.
getPlaylists,createPlaylist,updatePlaylist, anddeletePlaylistgive clients full control over collaborative and personal playlists that live on the server, so they follow you between apps. - Favorites and ratings.
starandunstarmark songs, albums, or artists as favorites;setRatingrecords numeric ratings. Because these live server-side, your five-star tracks look the same in every client. - Scrobbling. The
scrobbleendpoint registers a play event, updating play counts and “now playing” status, and can be bridged to services like Last.fm or ListenBrainz. This is how your listening history survives even as you switch apps. - Podcasts, internet radio, and the jukebox. The API reaches beyond a personal music library into podcast subscriptions, internet radio stations, and a “jukebox” mode that plays audio out of the server’s own audio device — useful for driving speakers attached to the machine itself.
For a developer, this is a gift. The unglamorous, genuinely difficult back-end work is already done, tested, and running on the user’s own hardware. What remains is the part many developers actually enjoy: designing a beautiful, responsive, pleasant experience for listening to music.
The authentication and streaming flow, demystified
Let us make this concrete, because the mechanics are simpler than newcomers expect, and seeing them removes the mystery.
Every request to a Subsonic-compatible server carries a small set of parameters that identify who you are, what version of the protocol you speak, and what your client is called. The historical approach sent the password directly, which is exactly as bad an idea as it sounds. The modern approach, introduced around API version 1.13.0, uses a salted token: the client generates a random salt, computes an MD5 hash of the password concatenated with that salt, and sends the token and the salt instead of the raw password. The server, which knows the password, computes the same hash and checks that it matches. The plaintext password never travels across the wire.
A minimal client’s very first move is almost always the same: call ping to confirm the server is reachable and the credentials work. Here is the whole handshake in illustrative pseudo-code:
python
import hashlib, os, requests
server = "https://music.example.com"
username = "ann"
password = "correct-horse-battery-staple"
# 1. Build salted-token auth (modern, recommended)
salt = os.urandom(6).hex() # random per session
token = hashlib.md5((password + salt).encode()).hexdigest()
# These parameters ride along on every request.
auth = {
"u": username, # who you are
"t": token, # md5(password + salt)
"s": salt, # the salt you just generated
"v": "1.16.1", # API version you speak
"c": "my-tiny-client", # your client's name
"f": "json", # response format: json or xml
}
# 2. Say hello. If this works, everything else will too.
resp = requests.get(f"{server}/rest/ping.view", params=auth).json()
status = resp["subsonic-response"]["status"]
print("server says:", status) # "ok" or "failed"
# 3. Ask for something to play — the newest albums, say.
albums = requests.get(
f"{server}/rest/getAlbumList2.view",
params={**auth, "type": "newest", "size": 10},
).json()
first_song_id = get_first_song(albums) # walk into an album, pick a track
# 4. Stream it. This URL *is* the audio; hand it to any player.
stream_url = f"{server}/rest/stream.view"
play(stream_url, params={**auth, "id": first_song_id, "maxBitRate": 320})
That is the essence of a Subsonic client. Authenticate, ping, browse, stream. The stream.view URL, with the right parameters attached, is a plain HTTP endpoint that returns audio bytes; you can hand it directly to a media framework, a <audio> element in a browser, or a native audio pipeline. The elegance is that the hardest infrastructural questions — where the files live, how they are indexed, whether they need transcoding — are answered on the far side of that URL. A developer building their first client can go from nothing to “music is coming out of my phone” in an afternoon.
Of course, the distance between that afternoon prototype and a polished app that people love is enormous, and that distance is exactly where the craft lives.
The craft: what building a good client really involves
Getting audio to play is easy. Building a client that feels effortless, respects the user’s time, and holds up on a subway with two bars of signal is hard. This is the work that separates a weekend experiment from an app someone opens every single day. A few of the genuine challenges:
Offline caching and ownership. The whole point of self-hosting is control, and control includes listening when the network does not cooperate. A serious client has to let users download albums and playlists for offline playback, manage how much storage that consumes, decide what to evict when space runs low, and keep the offline library coherent with the server when the connection returns. Getting this right — invisibly, without the user ever having to think about it — is one of the deepest problems in the whole space. Many of the most-loved apps advertise “smart caching” precisely because it is so hard to do well.
Gapless playback. Ask any developer in this community about gapless playback and you will get a knowing sigh. Many albums — live recordings, concept records, DJ mixes, classical works — are meant to flow from one track into the next with no silence at all. Achieving this means the client must begin decoding and buffering the next track before the current one ends, hand it to the audio pipeline seamlessly, and do so across formats and transcoding boundaries. It is a genuinely tricky engineering problem, and the fact that so many indie clients list gapless playback as a headline feature tells you how much users care and how much effort it takes.
Transcoding decisions. The server can transcode on the fly, but the client has to be smart about when to ask for it. Streaming lossless FLAC over a cellular connection wastes bandwidth and battery; streaming it over home Wi-Fi to a good DAC is exactly what an audiophile wants. Good clients let the user set different quality profiles for different networks and negotiate bitrate accordingly through the maxBitRate and format parameters.
State that follows you. Because favorites, ratings, play counts, and playlists live on the server, a client must sync them faithfully — pushing a “star” up, pulling down changes another device made, scrobbling plays even when they happened offline and need to be replayed later. The reward is profound: your listening life is consistent no matter which app you happen to open.
Platform integration. A music app that ignores the platform it runs on feels foreign. On Android that means Android Auto, Material You theming, and media notifications; on iOS it means CarPlay, Siri, lock-screen controls, and the Apple Watch; on the desktop it means keyboard media keys and an MPV or native audio backend; and increasingly it means Chromecast and Sonos and even Garmin watches and HarmonyOS phones. The Subsonic ecosystem stretches across all of these, because different developers scratch different itches on different devices.
None of this is required to technically speak the protocol. All of it is required to make something people love. That gap is where indie developers pour their evenings.
OpenSubsonic: the community takes the wheel
For years, the API’s greatest strength — its stability — was also becoming a liability. The original specification had aged. Its authentication story was dated. Its versioning was awkward. There was no clean way for a server to advertise which optional features it supported, and no collaborative process for evolving the protocol as needs changed. The spec was a fixed artifact from a project that had moved on, and the ecosystem that depended on it had no seat at the table.
So the community built its own table. OpenSubsonic is an open, collaboratively maintained specification that builds directly on top of the original Subsonic API. Its guiding principles are worth stating plainly, because they capture the ethos of the whole movement:
- Full backwards compatibility. An OpenSubsonic server still works with old Subsonic clients, and OpenSubsonic clients still work with old servers. Nobody’s existing setup breaks.
- Optional, piecewise adoption. Servers and clients can implement extensions individually rather than all at once, and there is a mechanism for a server to announce which extensions it actually supports. A client can then adapt gracefully.
- Security and consistency. The initiative explicitly targets the original API’s weak spots — outdated authentication, inconsistent behavior across servers — and aims for results that are predictable no matter whose server you point at.
- Open, collaborative evolution. Development happens in the open, with discussions and proposals anyone can read and contribute to. The protocol is no longer owned by a single vendor; it is a commons.
OpenSubsonic added the modern niceties people had been wanting for years: richer metadata, support for synced lyrics, better handling of multiple artists and roles, cover-art and formatting improvements, and a proper way to describe server capabilities. Crucially, it did this without a flag day, without breaking the enormous installed base of existing apps and servers. That is a remarkably mature way to steward a protocol, and it is entirely volunteer-driven.
The list of participants tells the story. On the server side, projects documented as supporting OpenSubsonic include Ampache, gonic, the Lightweight Music Server, Navidrome, Nextcloud Music, Supysonic, and others. On the client side, apps such as Amperfy, Feishin, Supersonic, Symfonium, Tempus, and more have adopted it. These are independent teams — many of them one-person operations — voluntarily converging on a shared standard because everyone benefits when the whole ecosystem speaks a richer common language.
A field guide to the client ecosystem
Part of what makes this community so alive is the sheer diversity of clients. Where a commercial streaming service gives you exactly one app, with exactly one design philosophy, the Subsonic world gives you a marketplace of visions. A tour of the landscape — bearing in mind that these projects evolve constantly, so treat any single detail as a snapshot rather than gospel:
On Android, the long-serving DSub has been a workhorse for years, known for gapless playback and jukebox mode, and it has inspired forks like DSub2000. Ultrasonic is a free, open-source option with Material You theming. Substreamer offers offline downloads. Tempo is a lightweight Material You player with Chromecast support, and Tempus forks it to add podcasts and radio. And then there is Symfonium — a paid, fiercely capable client famous for its deep customization and a graphic equalizer of almost absurd granularity — which has become a favorite of power users precisely because one determined developer kept pushing on the details.
On iOS, Amperfy stands out as an open-source client with CarPlay, podcasts, and Siri support, spanning iPhone, iPad, and Mac. play:Sub and iSub are long-standing native options; iSub is notable for handling many formats and offering a parametric EQ. A whole constellation of newer SwiftUI apps — many distributed through TestFlight — keep appearing, each chasing a slightly different ideal of what an Apple-native music player should feel like.
On the desktop, the picture is gloriously varied. Feishin offers a modern interface with an MPV backend and smart playlists. Supersonic is a cross-platform client, also MPV-backed, with a fifteen-band equalizer. There is a striking cluster of clients written in Rust — fast, lightweight players and even terminal-based ones for people who want to control their music without leaving the command line. Strawberry serves audiophiles who want serious collection organization. Older projects like Sonixd and Sublime Music helped establish the desktop category and influenced what came after.
On the web, progressive web apps and lightweight React and HTML5 players let you stream from any browser without installing anything — handy on a work machine or a borrowed laptop.
And then the long tail: Sonos integration bridges, Kodi add-ons, a Garmin watch app, HarmonyOS clients, tvOS players. Wherever there is a screen and a speaker, someone in this community has decided their music should reach it, and has written the code to make it so.
No corporate roadmap produced this variety. It emerged, bottom-up, from hundreds of individual decisions by developers who each wanted something slightly different and were free to build it — because the API was open, the servers were interoperable, and the door was never locked.
Why they do it: the ethos of the indie client author
It is worth pausing on the human question. Why would someone build one of these? There is little money in it. Some clients are paid, and a few developers earn a modest living, but most of this work is done for love, released under open-source licenses, and supported by nothing more than gratitude and the occasional donation.
The honest answer is a blend of motives, and every developer in this world would recognize all of them. There is the itch — the specific, personal frustration of wanting a music app that works exactly the way you think, and realizing that because the API is open, you can just make it. There is the craft — the deep, absorbing pleasure of solving gapless playback or nailing an offline cache, problems meaty enough to be worthy of a real engineer’s attention. There is the gift economy — the knowledge that publishing your work means a stranger halfway across the world gets to enjoy their music collection a little more, and might send back a bug report, a translation, or a pull request that makes the thing better for everyone.
And underneath it all there is principle. Many of these developers are motivated by a genuine belief that people should own their culture. They have watched songs vanish from streaming catalogs overnight because of a licensing dispute. They have seen services shut down, playlists evaporate, and “your library” turn out to mean “a library we are renting to you until we change our minds.” Building a Subsonic client is a small, concrete act of resistance against that fragility. It says: your music, on your hardware, played by software you can read and modify, going nowhere unless you decide it goes.
That is a developer culture with a moral spine, and it is quietly beautiful.
Saving your music collection — literally and figuratively
The word “save” in the title is deliberately double-edged. There is the everyday sense — saving a file, saving a playlist, downloading an album for the flight. And there is the deeper sense — rescuing, preserving, keeping safe.
For a long time, the story of digital music trended toward dispossession. We traded shelves of CDs and folders of files for the convenience of streaming, and in doing so we handed control of our listening lives to a handful of companies. Convenient, yes — but rented. The catalog can change. The recommendations can nudge. The service can disappear. And the collection you spent years curating was never really yours at all.
The Subsonic ecosystem is a working, practical answer to that predicament, and its answer is refreshingly unromantic. Run a server on hardware you own. Point it at the music you have gathered — ripped, purchased, downloaded from artists directly, whatever. Pick a client, or five clients, that you like. Now your collection lives where you can see it, plays through software you can inspect, follows you across every device you own, and survives any corporate decision made by anyone anywhere. If one client stops being maintained, you switch to another that speaks the same protocol, and your favorites and playlists and play counts come along, because they live on your server, not in an app.
This is what “saving your music” means in 2026. It is not nostalgia for physical media. It is a modern, networked, genuinely convenient form of ownership — one that gives you the seamless streaming experience the commercial services taught us to want, without the leash. And it exists only because a loose, global, largely unpaid community of developers decided that a shared open protocol was worth building clients for, again and again, in dozens of flavors, for every platform under the sun.
From code to stage
Return, for a moment, to where we began. A developer opens an editor late at night. They write a few lines to compute a salted token, fire a ping at a server running in someone’s spare room, and get back a single reassuring word: ok. From that handshake grows a browse view, then a now-playing screen, then the long tail of hard problems — caching, gapless transitions, CarPlay, offline sync — that turn a technical demo into something a person reaches for every morning. From code, patiently, to stage: to the moment the music actually plays, and a listener never has to think about any of the machinery that carried it to their ears.
That arc, repeated across hundreds of projects and thousands of contributors, is the real achievement of the Subsonic world. It is not any single app, however elegant. It is the whole living system: an open API that refused to die, a community initiative in OpenSubsonic that gave it a future, a constellation of interoperable servers, and an unruly, generous, opinionated crowd of indie developers who keep building clients because they believe your music should belong to you.
They are not doing it for the money, and they are not doing it for the fame. They are doing it because a song you love should be a thing you own, and because writing the code that makes that true is, in its own quiet way, a form of art. From code to stage — and the collection, at last, is saved.
Sources and further reading: the OpenSubsonic documentation and project repository; the original Subsonic API reference; Navidrome’s overview, Subsonic API compatibility notes, and client apps directory; and Ampache’s Subsonic API page. Specific feature details for individual clients and servers change frequently; treat any single description here as a snapshot rather than a permanent fact.

