Spotify has this feature that allows you to play tracks in your spotify client from a control within a browser. This is really cool because it let’s developers embed playlists or songs into their site, and allows users to play them directly in their desktop client. Powerful stuff; what if we take control ourselves.
The problem with the embedded web control is painfully obvious. There’s simply no way to control the client. Sure, you can play a specific playlist, or a specific track, but you can’t say “hey, just go to the next track”. What a bummer. One of the projects I’ve been working on for a while is Partify. Partify is designed to put the party-goers in control of the music at an event. Don’t like a track? Downvote it. If a track get’s enough downvotes, we’ll skip it. Simple, easy, cool. So how can we do that?
Well luckily, The web controls take advantage of the fact that every Spotify client is also a web server. Mind blown? Cool. So what’s this mean? Well, Spotify own’s the domain spotilocal.com. This domain simply points at 127.0.0.1, or localhost. This means that they have a sure-fire way to issue web requests to your local machine. Now, that webserver running within Spotify can handle these requests. Damn, that’s awesome.
There’s a few tricks to sending requests from a browser to a spotify client though. Most (read: all) browsers allow only one connection to a server at once, which would mean only one spotify control could be running per page. To bypass that limit, the web control’s actually connect to different subdomains @ spotilocal.com. These are seemingly random, and generated on the fly with a low collision algorithm. So now they’ve solved that. All that’s left is knowing what port to use when they connect to the local server. Spotify can’t use the same port on every computer, because depending on what other applications are running, they may not be able to listen on a specific port. So instead of hardcoding a port, they simply set a port range, and have the web controls issue requests to each port, and see what sticks. The Spotify client has the same port range, and does the same thing when you launch spotify, trying to listen on a port, and moving to the next one if they can’t listen properly (due to another application being there already). So that’s solved too.
So now the web controls can communicate with the client, using http requests. However, if they left it just like that their system wouldn’t be secure, and anyone could issue requests that mess with the Spotify client. That’s probably not great for business, so they secured things a bit. Enter CSRF and OAUTH. Spotify provides a simple endpoint of the local webserver to request csrf tokens from (as of v0.9 this is /simplecsrf/token.json), and an endpoint (as of v0.9 this is http://open.spotify.com/token) to get an oauth token from. The oauth endpoint can only be queried from spotify.com domains in most (non-hacked) browsers, meaning that this solution is pretty secure for a web based approach. However, we can get both tokens from a non-browser (like curl) really easily.
C# made it really easy to get something up and running that was capable of querying both the oauth endpoint, and the csrf endpoint. Spectacular.
The test application worked really well! I used C# cause it was insanely easy to make web requests, and this was just a basic proof of concept. Not sure what we’d use for Partify. If I go ahead and clean the code up a bit and add support for sending the play request, it’ll be a bit more interesting.
Another 8 minutes and play started working. We’ve got good control, without any issues! Works exactly like the spotify official solutions; granted not within a browser.
I’ll probably end up abstracting this out to a c library, or something along those lines so that we can reuse the code across different platforms.
So what’s the tl;dr?
- Spotify uses a local web server to provide browser control
- The server is secured with csrf and oauth that you can’t fake in a browser.
- You can fake that in a client (curl, custom, etc)
- You can send requests to control Spotify after you connect securely.
Hopefully this can help people write applications that control Spotify much more effectively than just media key simulators (http://goo.gl/90bT7H) and window title reading (http://goo.gl/h83nzA). If this kind of thing is interesting to you, follow me on twitter!🚀