My favorites | Sign in
Logo
                
Search
for
Updated Feb 27, 2009 by jopsen
Labels: Featured
LastFM12UnofficialDocumentation  
An unofficial documentation of the Last.fm protocol version 1.2

Copyright 2007 by Tobias Brennecke (tburny), Jonas F. Jensen (Jop...), Matt Brown (blueboxed) and Moritz StrĂ¼be (morty). Release under CreativeCommons Attribution Non-commercial Share Alike (by-nc-sa).

Introduction

This document is to be used in compliment of existing documentation. For more information, refer to the following pages: Audioscrobbler Protocol v1.1, Audioscrobbler Protocol v1.2. For web services 2.0 documentation, please see Web services 2.0 documentation on last.fm.

Conventions Used in this Document

In order to avoid redundancy, some conventions and abbreviations are used in this document.

List of Conventions

List of Abbreviations

Handshake

An intial handshake/login, consists of a request and a response.

Please Note: This handshake is for the old web services 1.0, but is also used nowadays for radio functions.

Request

Example:

http://ws.audioscrobbler.com/radio/handshake.php?version=1.3.1.1&platform=win32&username=[USERNAME]&passwordmd5=[PASSWORDMD5_HASH]&language=de&player=[player]

Post Variables:

Response

Example:

    session=ae1eb54a11615e605d61d6e83dde71bc
    stream_url=http://87.117.229.85:80/last.mp3?Session=ae1eb54a11615e605d61d6e83dde71bc
    subscriber=0
    framehack=0
    base_url=ws.audioscrobbler.com
    base_path=/radio
    info_message=
    fingerprint_upload_url=http://ws.audioscrobbler.com/fingerprint/upload.php

Results:

Second Handshake/Scrobbler Handshake

This handshake is new in the 1.2 version of the last.fm protocol, it's not needed if you only want to request an XSPF.

Request

Example:

    http://post.audioscrobbler.com/?hs=true&p=1.2&c=ass&v=1.3.1.1&u=[USERNAME]&t=[TIMESTAMP]&a=[Token] 

Post Variables:

Response

Example:

    OK
    be290d5d491e1bedb21e0c35f74ce96b
    http://post.audioscrobbler.com:80/np_1.2
    http://87.117.229.205:80/protocol_1.2

Results:

  1. The first line indicates whether the previous post was successful. kv: "OK", "FAILED". Note there may be other values returned.
  2. The second line indicates session id (a.k.a session key).
  3. The third line contains the URL to post Now Playing information.
  4. The fourth line contains the URL to post unknown information. The usage of this is unknown.

Adjusting Radio Station

Adjustment of radio station is still done the same way as it was in the 1.1 protocol.

Request

Example:

    http://[base_url][base_path]/adjust.php?session=[sessionID]&url=[LASTFMURI]&lang=[LANGUAGE]

Post Variables:

Response

The following response indicates that the information posted to Adjust.php was accepted:

    OK

The following response indicates that the information posted to Adjust.php was rejected:

    FAILED

Requesting an XSPF

This feature is new in version 1.2.

For more information on the XSPF (XML Sharable Playlist File) format created by Xiph OSC, please refer to the official XSPF documentation (http://www.xspf.org/).

Request

Example:

    http://[base_url][base_path]/xspf.php?sk=[SESSIONID]&discovery=0&desktop=1.5.1

Post Variables:

Response

The response is an XSPF. It conforms to all of the require XSPF tags specified in the XSPF standard; but also contains the following additional tags: lastfm:trackauth, lastfm:albumId, lastfm:artistId. Additionally, the playlist tag is written incorrectly.

The presence of these additional tags, and the incorrectly written playlist tag, make the XSPFs generated not compliant with the XSPF standard.

Please read below the following example for additional information on the specific tags as they relate to Last.FM.

Example of an XSPF returned by xspf.php:

<playlist version="1" xmlns:lastfm="http://www.audioscrobbler.net/dtd/xspf-lastfm">
<title>+%C3%84hnliche+K%C3%BCnstler+wie+Meat+Loaf</title>
<creator>Last.fm</creator>
<link rel="http://www.last.fm/skipsLeft">6</link>
<trackList>
    <track>
        <location>http://kingpin4.last.fm/user/d87034ad6ab5d7ed388a6dcd2d2df506.mp3</location>
        <title>Killer Queen (Live)</title>
        <id>3647300</id>
        <album>Live Killers</album>
        <creator>Queen</creator>
        <duration>118000</duration>
        <image>http://images.amazon.com/images/P/B000000OAP.01._SCMZZZZZZZ_.jpg</image>
        <lastfm:trackauth>15fcf</lastfm:trackauth>
        <lastfm:albumId>2553849</lastfm:albumId>
        <lastfm:artistId>1270</lastfm:artistId>       
        <link rel="http://www.last.fm/artistpage">http://www.last.fm/music/Queen</link>
        <link rel="http://www.last.fm/albumpage">http://www.last.fm/music/Queen/Live+Killers</link>
        <link rel="http://www.last.fm/trackpage">http://www.last.fm/music/Queen/_/Killer+Queen+%28Live%29</link>
        <link rel="http://www.last.fm/buyTrackURL">http://www.last.fm/affiliate_sendto.php?link=uapc&amp;prod=731771&amp;pos=9b944892b67cd2d9f7d9da1c934c5428</link>
        <link rel="http://www.last.fm/buyAlbumURL"></link>
        <link rel="http://www.last.fm/freeTrackURL"></link>
    </track>
    <track>
        <location>http://kingpin4.last.fm/user/4c0ae6e135aa0d4c4926fa29a633911e.mp3</location>
        <title>Going, Going... Home</title>
        <id>4195329</id>
        <album></album>
        <creator>Mike &amp; The Mechanics</creator>
        <duration>269000</duration>
        <image></image>
        <lastfm:trackauth>86776</lastfm:trackauth>
        <lastfm:albumId></lastfm:albumId>
        <lastfm:artistId>1000520</lastfm:artistId>       
        <link rel="http://www.last.fm/artistpage">http://www.last.fm/music/Mike%2B%2526%2BThe%2BMechanics</link>
        <link rel="http://www.last.fm/albumpage"></link>
        <link rel="http://www.last.fm/trackpage">http://www.last.fm/music/Mike%2B%2526%2BThe%2BMechanics/_/Going%2C+Going...+Home</link>
        <link rel="http://www.last.fm/buyTrackURL"></link>
        <link rel="http://www.last.fm/buyAlbumURL"></link>
        <link rel="http://www.last.fm/freeTrackURL"></link>
    </track>
	...
	...
	...
</trackList>
</playlist>

Detailed Explanation:

This is a playlist. its version is "1".... <title> says to the app which title the playlist has <creator> says the creator is "last.fm"(in this case). Now the first really interesting thing: The content of the <link> tag says after how many skips(or plays of songs) the playlist has to be reloaded.

Now let's take a look on one of the track nodes. It contains (tag identified here by xpath):

  • playlist/title = title of the radio station
    • playlist/creator = creator of the playlist, usually last.fm
    • playlist/link?rel="http://www.last.fm/skipsLeft" = Number of tracks on this playlist
      • playlist/trackList/track/location = The location of the mp3 file/track->where can the client download it
      • playlist/trackList/track/title = The track title
      • playlist/trackList/track/id = The id of the track in the last.fm music catalog, could be used for adding this track to the personal playlist(I'll say a few words to this topic later in the text)
      • playlist/trackList/track/album = The album name
      • playlist/trackList/track/creator = The Artist
      • playlist/trackList/track/duration = The duration, in milliseconds(really nonsense, except for id3 tagging maybe :P)
      • playlist/trackList/track/image = Url to the album picture
      • playlist/trackList/track/lastfm:trackauth = 5-hexdigit Last.fm recommendation key (appended to the 'L' source ID when submitting track data via Audioscrobbler Protocol v1.2)
      • playlist/trackList/track/lastfm:albumId = Id of the album. seems to be worthless
      • playlist/trackList/track/lastfm:artistId = same thing as with the album
    • links to last.fm's artist-, album- and track pages
    • a url from where you can buy the track
    • another one for the album
    • freeTrackurl: If the song is downloadable for free, this is the download link

Test User/Pass

This way you can check, whether a user/pass is valid.

Request

Example:

http://ws.audioscrobbler.com//ass/pwcheck.php?time=[TIMESTAMP]&username=[USERNAME]&auth=[AUTH1]&auth2=[AUTH2]&defaultplayer=[PLAYER]

Post Variables:

Response

The following response indicates that the information posted to Adjust.php was accepted:

OK-8

Response may contain the following strings:

Appendix A: List of Last.FM URIs

Appendix B: List of Accepted Client Names


Comment by easterdom, Oct 29, 2007

lastfm://user/$username/playlist

Comment by PekeDDVC, Nov 28, 2007
lastfm://play/tracks/$trackid,$trackid,$trackid
"," is used as Separator and no separator at the end
$trackid = playlist/trackList/track/id returned by xspf.php as explained Above
Comment by morty@gmx.net, Dec 09, 2007
Comment by ge...@vdcruijsen.net, Jan 01, 2008

does anyone know how you can get the remaining time from the current song? as i see it you only get the total amount of time of a song

Comment by jopsen, Jan 01, 2008

the remaining times can be calculated as: <total time> - <downloaded bytes> 128

Comment by ge...@vdcruijsen.net, Jan 03, 2008

hmm im really far now building my windows sidebar last.fm player.

the error im getting now is "FAILED Incorrect Timestamp Format." at the handshake. I'm Using the 1.2 protocol.

the way i create the timestamp is with this javascript code:

    var now = new Date();
    now.setHours(now.getUTCHours(),now.getUTCMinutes(),now.getUTCSeconds(),now.getUTCMilliseconds());
    alert(now.getTime());

as auth code i send a md5

(md5(password)+now.getTime());
Comment by ge...@vdcruijsen.net, Jan 03, 2008

oops as auth i ment

md5(md5(password)+now.getTime());
Comment by jopsen, Jan 03, 2008

It must be a Unix timestamp, according to wikipedia:

it is the number of seconds elapsed since midnight UTC of January 1, 1970, not counting leap seconds.

You can probably find a javascript that does that somewhere in the wild.

Comment by ge...@vdcruijsen.net, Jan 03, 2008

doh.. my fault.

my timestamp was milliseconds instead of seconds.

    var now = new Date();
    now.setHours(now.getUTCHours(),now.getUTCMinutes(),now.getUTCSeconds(),now.getUTCMilliseconds());
    var time = parseInt(now.getTime()/1000.0)

works perfectly

btw im going to build a Windows Vista Sidebar gadget that can play the last.fm stream. I'm writing on my blog how to do this atm. (will be later up today @ http://www.vdcruijsen.net

Comment by ge...@vdcruijsen.net, Jan 04, 2008

Did anyone ever get the following error:

response=FAILED error=8

I got this error after changing the radio station with the adjust.php call.

Comment by ge...@vdcruijsen.net, Jan 04, 2008

hmm i dont have the response=failed error = 8 anymore. i dont know what happened but now it doesnt come up again.

i do have some last troubles implementing my tool.

my tool can now send handshake. change channel, play the stream. send "now playing" info and can submit/srobble songs.

my only problems are at "now playing" and "submitting/scrobbling". i post these values as a POST request to the server and i get a OK as result back (so you would guess everything is ok) problem is.. it isnt :(

the now playing and submitted songs arent showing up on the website. does anyone know what could be the problem?

here is the submit that i captured with wireshak

POST /protocol_1.2 HTTP/1.1
Accept: */*
Accept-Language: nl
Referer: file://C:\Users\Geert\Desktop\radio\last.fm radio\lastfm.html
Content-Type: application/x-www-form-urlencoded
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; .NET CLR 3.5.21022)
Host: 87.117.229.205
Content-Length: 145
Connection: Keep-Alive
Cache-Control: no-cache

s=9b9e2e43701f4a90ba15ac697e77ee7f&a[0]=Razorlight&t[0]=Dalston&i[0]=1199486491&o[0]=L9f12f&r[0]=&l[0]=&b[0]=Up All Night + Bonus Dvd&n[0]=&m[0]=

and this was the response

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Pragma: no-cache
Cache-Control: no-cache
Content-Type: text/plain;charset=ISO-8859-1
Date: Fri, 04 Jan 2008 23:44:09 GMT
Connection: close

OK

I dont see whats wrong in this :(

Comment by rbok002, Jan 07, 2008

Is there anyway to listen to the radio without logging in?

Comment by morty@gmx.net, Feb 11, 2008

@vdcr...: Listening to tracks isn't enaugh. You have to scrobb them: http://www.audioscrobbler.net/ The Idea is, that you can add any track - LastFM or not - to your playlist.

@rbok002: No

Comment by jopsen, Feb 11, 2008

#rbok002 It's possible, however the process is not yet documented here. I wiresharked a last.fm widget the other day, and using a widget ID it should be possible...

If anyone wants to document that process you're welcome to leave comment here, I don't we'll document it anytime soon...

Comment by hartwig.christian, Feb 18, 2008

Hi everybody!

What does the errorcode "5" stand for, which is returned from "adjust.php"?

I have searched but I didn't find a listing of that error-codes.

Comment by hartwig.christian, Feb 18, 2008

Hi!

I've posted my problem at last.fm, too. And there is a complete(?) list of codes which can be returned: http://www.lastfm.de/forum/21716/_/380495/1#f5829688

Comment by hartwig.christian, Feb 18, 2008

Hello again!

Now I have another problem, I hope you can help me. This is an example playlist, which I get when I request a xpsf (just a part of it):

<playlist version="1" xmlns:lastfm="http://www.audioscrobbler.net/dtd/xspf-lastfm"> <title>My+Neighbourhood</title> <creator>Last.fm</creator> <link rel="http://www.last.fm/skipsLeft">6</link> <trackList>

<track>
<location>http://kingpin6.last.fm/user/87c7b1857cdca5af52fa5b68bed4a068.mp3</location>

In location is the "path"/url to the mp3 file stored, from which my player can play the song (I pass it to a windows media player object in my app). But windows media player can't find that location. What's wrong? Have I missunderstood something?

Comment by jopsen, Feb 18, 2008

@hartwig.christian First, thanks for the info about errorcodes... With regards to your app it depends on media players abilities... <location> tag contains the address to a binary mp3 file that you can download using http, as noted in the URI. I don't know if you interface to media player supports http URI or only URLs to local storage, try downloading the song to a temporary file and then play it... But it depends on which platform you're implementing on top of..

Comment by bjorn.linse, Jun 22, 2008

To play a full-length track with a track URI (lastfm://play/tracks/012345) try the following url:

http://[base_url]/1.0/webclient/getresourceplaylist.php?sk=[sessionID]&url=[LASTFMURI]&desktop=1

It returns an xspf directly, but when I tried to download the MP3 file, I got a 400 Bad Request.

I found out, you have to send "Cookie: Session=[sessionID]" in the header of the request of the MP3 file.

Comment by manoftomorrow, Jun 25, 2008

@jopsen: It's fairly straight-forward to get a radio playlist without signing in (and similar to the regular process):

1. XML-RPC call to

http://ext.last.fm/1.0/webclient/xmlrpc.php
  • method: getSession ("<methodCall><methodName>getSession</methodName><params /></methodCall>")
  • returns a session id and username "LFM_ANON"

2. Create a timestamp

3. Handshake with the webclient url:

http://ext.last.fm/1.0/radio/webclient/handshake.php?sessionKey=[SESSIONID]&user=LFM_ANON&timestamp=[TIMESTAMP]
returns something like:
session=7a5510dfb03e3eaee9fd44661a91d5c4&playlist_url=http://www.last.fm/flash_getplaylist.php&subscriber=0&base_url=ext.last.fm&base_path=/radio/

4. Adjust the radio station (build the url from returned response in step 3):

http://[base_url][base_path]adjust.php?user=LFM_ANON&session=[SESSIONID]&timestamp=[TIMESTAMP]&url=[LASTFMURI]&lang=en

5. Get the playlist:

[playlist_url]?sk=[SESSIONID]&y=[TIMESTAMP]
(playlist_url returned in step 3) returns base64 + url-encoded playlist
Comment by MatthewBrown, Jul 05, 2008

^zomg thanks

Comment by jamieb122, Jul 28, 2008

I am writing a client and Java, I can sign in, Tune a radio station, and stream the mp3 files. To download the file directly I parse the mp3 from the xspf xml file. When I try to download it I get a HTTP 403 error and a response of invalid ticket. When I tune the radio and request the XML file I send the Cookie: Session=SESSION_ID?. Does anyone have any hints on what I could be missing in my requests?

Comment by henkesn, Aug 16, 2008

Hello, I'm just writing a player in javascript. Where do I get the id3 tags from?

Comment by jopsen, Aug 17, 2008

If it's a last.fm player you wont find id3 tags, but you may get metadata from the XPSF... If you are writing a javascript mp3 player I have no idea, and this is the wrong place...

Comment by henkesn, Aug 17, 2008

Thank you for your answer. Am I right, that with the change to protocol 1.2 the usage has changed as follows: the stream is not played directly from stream_url but i have to get the xspf playlist an then play the streams included? In this case, skipping would noch be the http request to control.php anymore (which doesn't function) but just changing the stream url to the next one from the playlist. It's just to understand the usage of all this stuff, the programing language is not important.

Comment by jopsen, Aug 17, 2008

Yes, you are right...

Comment by henkesn, Aug 18, 2008

Thank you for your help. I works randomly now. Do I definitly need to send the cookie session with the http mp3 request? If yes, does anybody know how to do this with Windows Media Player?

Comment by henkesn, Aug 18, 2008

Hello, me again. I'm still stuck with this problem. In detail: sometimes i get an "invalid ticket - 403" http status code and sometimes not. I've captured the requests using a packet sniffer. The requests are (except the url) exactly the same. Strange is: after having one url which returns no 403, i can skip without problems. Often, I get playable URLs when refreshing the playlist and using the new locations.

PS.: I'll release my javascript API after having done this hole stuff, so it's getting easier for further programers to get through the lastfm streaming system.

Comment by jopsen, Aug 19, 2008

I've got no idea... Probably instability at last.fm serverside... That is NOT uncommon... The cookies shouldn't be needed...

Comment by henkesn, Aug 20, 2008

Hm I think I've got the reason. Obviously only tracks seem to work which are marked in lastfm as "full length". Perhaps for the other ones, the cookie is needet. I'll try to use a proxy which modifies the http header of media player's request later. I'll keep you up to date. The lastfm software sends this cookie, by the way.

Comment by ingmar.runge, Feb 26, 2009

I was able to work around the 403 issue by replacing "kingpin5.last.fm" with "play.last.fm" in the URLs returned by xspf.php. Without sending the Session cookie. Probably a hack, but it seems to do the trick.

Comment by jopsen, Feb 27, 2009

@ingmar.runge I've discovered that if you do pass desktop=1.5.1 instead of desktop=1.3.1 when requesting the xspf, you get tracks starting with play.last.fm instead of kinpin5.last.fm... I guess we should just update the client id once in a while :)

Note: documentation have been update with this fix...


Sign in to add a comment
Hosted by Google Code