Exploring the Last.fm Web Service API

Last.fm listeners get custom radio and all the benefits of the social network that drives its selections. Last.fm developers get access to a huge network of data linking listeners, preferences, artists, and tracks. Learn to wire Last.fm into your application before you attend Hack Day. 


Sidebar: Last.fm in Silverlight
For Silverlight developers, working with the Last.fm API is mostly a matter of using WebClient to send requests to the Last.fm server and using LINQ to query the XML document that comes back in response.

We'll use a little example application to walk through this approach. The example Silverlight application shows two list boxes, one for Artists, and one for Events. Both lists start out empty. When you click the "Get Artists" button, the application calls the Last.fm API to fetch the top artists for a given (hard coded) user. Then, when you click on an entry in the Artists list, the application calls Last.fm to get any events associated with that artist, and displays them in the results list. The screenshot below shows the example with both lists populated.

A Silverlight example application that uses two Last.fm calls to retrieve artists and events.

When the button is clicked, we build the request URL and hand it off to WebClient:

private void FetchButton_Click(object sender, RoutedEventArgs e)

{

ArtistsList.Items.Clear();

EventsList.Items.Clear();

string getTopArtists =        "http://ws.audioscrobbler.com/2.0/method=user.gettopartists&user=xxx&api_key=xxx";

WebClient client = new WebClient();

client.DownloadStringCompleted += new        DownloadStringCompletedEventHandler(getTopArtists_DownloadStringCompleted);

client.DownloadStringAsync(new Uri(getTopArtists));

}

We set up a download complete event handler, then call the download method. WebClient retrieves the response document asynchronously, then calls our handler. In the handler, we use LINQ to write queries against the parsed XML document:

            XDocument doc = XDocument.Parse(e.Result);

           

            //get the list of artist names.

            var artists = from results in doc.Descendants("artist")

                          select results.Element("name").Value.ToString();

           

            foreach (string artist in artists)

            {

                ArtistsList.Items.Add(artist);

            }

The code above walks through each "artist" element in the returned XML and extracts the text from the "name" sub-element. Then we add each artist name to the listbox.

When the user clicks an artist name, we use the same WebClient and LINQ combination to get the events for the selected artist. This time, we build an artist.getEvents Last.fm API call from the selected artist name like this:

string artist = ArtistsList.SelectedItem.ToString();

string getEvents = string.Format(

"http://ws.audioscrobbler.com/2.0/?method=artist.getevents&artist={0}&api_key=xxx", artist);

When that call returns, we again use LINQ to extract the event information we're looking for and populate the events list box.

  var evts = from results in doc.Descendants("event")

             select new

             {

                 title = results.Element("title").Value.ToString(),

                 venueName = results.Element("venue").Element("name").Value.ToString(),

                 startDate = results.Element("startDate").Value.ToString()

             };

  EventsList.Items.Clear();

  foreach (var evt in evts)

  {

     EventsList.Items.Add(evt.title + " at " + evt.venueName + " on " + evt.startDate);

  }

As these examples show, WebClient and LINQ make it relatively easy to consume REST-style web services, such as Last.fm, in Silverlight. And because WebClient works asynchronously, you can fetch data from Last.fm without interfering with the main UI.

Last.fm is Internet radio tuned to the taste of each listener, guided by personal listening history and by the collective selections of the crowd. Last.fm is also a social networking site that maps the connections between artists, tracks, and users. Exploring those connections on the http://Last.fm is a great way to discover new music and new artists (wandering freely around those connections is a great way to fritter away an afternoon). Sounds great, you say. But wouldn't this all be more fun if I could do it in code?

Turns out, you can. The http://www.last.fm/api is a collection of HTTP web services that give developers access to the wealth of music and listening data amassed by the site, including artist, album, and track information, popularity rankings, tags, and similarity recommendations. You can also write user-related data (such as user tags for a track) through the API, making it possible to build limited Last.fm clients. Finally, the API supports submitting user listening information to Last.fm for recording in user listening history (what Last.fm calls "scrobbling"). The one thing you can't currently do through the API is stream music, meaning you can't write a Last.fm player application using the web service.

To use the Last.fm API you need an API key, and (for some calls) a shared secret, both of which you can get from Last.fm through a free API account.

Calling Last.fm
Last.fm provides two API flavors, a REST-style interface that uses HTTP GET and POST and returns XML, and an XML-RPC interface. The two APIs are similar, except for the actual request and response formats. I'll focus on the REST-style interface in this article.

Because the Last.fm API is served up through HTTP, you can work with it from any platform with access to web services, including web applications, desktop applications, and mobile devices. Depending on the type of application you are building, there are a number of techniques for working with REST web services using .NET 3.5. The details are outside the scope of this article, but the links below are good resources (also see the sidebar, "Last.fm in Silverlight," for an example of working with the API from a Silverlight client).

Except for the scrobbler API, all of the Last.fm web service calls are made to URLs based at http://ws.audioscrobbler.com/2.0/.  For write calls, method and parameters are POSTed to this URL. For read calls, the query string specifies the method and any parameters, for example:

http://ws.audioscrobbler.com/2.0/?method=tag.getTopTags&api_key=xxx

This URL specifies the tag.getTopTags method and supplies the API key associated with the application. Methods are grouped into packages. This example, tag.getTopTags, is part of the tag package, which includes all calls related to user tags.

All of the calls that write data and a few of the user-specific read calls require user authentication. Your application can only make these kinds of requests on behalf of a registered Last.fm user. Last.fm exposes a user authentication API through its auth package.

The authentication mechanism varies from platform to platform, but the desktop and web mechanisms are similar. The basic idea for non-mobile devices is that your application obtains a short-lived token that is associated with a logged-in user and then uses this token to retrieve a long-lived session key from the server. The session key allows you to make authenticated calls. Users authenticate on the Last.fm site, so your application never handles user credentials directly.

In addition to the session key, authenticated calls also require a method signature. The signature is a hash of the method and its parameters along with the shared secret that you received with the API key. The application must generate a method signature for each authenticated call.

Data for All
Most of the data you can pull from Last.fm does not require authentication. This includes information on artists, albums, tracks, and users that you can use for visualization, tracking, and comparison in your applications.

There are 12 packages in the main API, including auth. Most of these packages contain all the functions related to a certain entity type, such as a user or an artist. The packages are:

·         album               Functions related to albums, including text search.          

·         artist                 Artist information, including events, fans, and similar artists.

·         auth                  User authentication.

·         event                Event information.

·         geo                   Location-based data on artists, events, and tracks.

·         group                Fetch charts associated with user groups.

·         library               Read or write artists, albums, and tracks to a user library.

·         playlist              Read, create, and add tracks to playlists.

·         tag                    Tag functions, including getting associated artists and tracks.

·         tasteometer       Compares users and returns a similarity score and shared artists.

·         track                 Track functions, including similar tracks, ban, and love.

·         user                  User information.

Many of the entity-type packages include sets of similar functions, such as getInfo or search. For illustration, here is the full method list for the track package:

·         track.addTags               Authenticated. Add a tag for the track for the given user.

·         track.ban                      Authenticated. "Ban" a track for a given user.

·         track.getInfo                  Get information for the track, including artist and length of track.

·         track.getSimilar            Get tracks that are similar to this track.

·         track.getTags                Authenticated. Get tags for this track for the given user.

·         track.getTopFans          Get top fans (users) for this track.

·         track.getTopTags          Get most frequently assigned tags for this track.

·         track.love                      Authenticated. "Love" a track for a given user.

·         track.removeTag            Authenticated. Remove a tag from this track.

·         track.search                  Text search for tag.

·         track.share                    Authenticated. Share track with another user.

The track.getTopFans and track.getTopTags methods are used to lookup related entities, starting with a track. Similarly, you can use artist.getTopTracks to look up the most popular tracks for an artist. Figure 1 is an illustration of some of the methods that relate the main Last.fm entities to one another.

Figure 1. You can navigate through the main entities in the Last.fm API through a series of lookup methods.

Let's look at how you might use API calls to construct a simple application to find events that might be of the most interest to a Last.fm user. This application would not require authentication, although the user would have to enter his or her username.

First, we might call user.getTopArtists, using the following URL:

http://ws.audioscrobbler.com/2.0/?method=user.gettopartists&user=xxx&api_key=xxx

This would return an XML document with a list of artists. The fragment below shows the top of the document, through the first artist.

<?xml version="1.0" encoding="utf-8"?>

<lfm status="ok">

<topartists user="xxx" type="overall">

<artist rank="1">

    <name>Squeeze</name>

    <playcount>124</playcount>

    <mbid>0509a681-a362-4800-9075-656041dccdbd</mbid>

    <url>http://www.last.fm/music/Squeeze</url>

    <streamable>1</streamable>

    <image size="small">http://userserve-ak.last.fm/serve/34/48192.jpg</image>

    <image size="medium">http://userserve-ak.last.fm/serve/64/48192.jpg</image>

    <image size="large">http://userserve-ak.last.fm/serve/126/48192.jpg</image>

</artist>

<artist rank="2">

...

 

 

The application parses the XML response to extract the list of artists. Then we can call artist.getEvents for each of the artists in the list:

http://ws.audioscrobbler.com/2.0/?method=artist.getevents&artist=Squeeze&api_key=xxx

And again, each call would return an XML response containing a list of events (if there are any scheduled) for the given artist.  The application parses the XML to extract event information, and presents the list of events to the user.

Other Methods
These un-authenticated APIs are ideal for the kind of data exploration and analysis described above. Last.fm's authenticated APIs are for a different purpose, allowing you to develop user profile management applications. The authenticated APIs include calls for applying and removing tags, for working with the user library, and for creating and editing playlists. All of Last.fm's calls that write data to the server are authenticated.

One additional un-authenticated method deserving of specific mention is tasteometer.compare, the only method in the tasteometer package. tasteometer.compare takes as arguments two items to compare; the items must be either Last.fm users, Myspace users, or lists of artist names. The call returns a similarity score that reflects common musical "tastes" between the two users (or between a user and a set of artists). It also returns a list of artists that the two items have in common.

Last.fm bases its recommendations on songs that users listen to, whether through the Last.fm client software, through the web, or through portable devices. Third-party media players can scrobble track selections to Last.fm using the Last.fm submissions protocol and a separate web service based at http://post.audioscrobbler.com:80/. The submission API is different from the rest of the Last.fm APIs, with its own authentication method and its own response formats. If you are developing a media player, you can get additional information on the submissions API and the submissions protocol at http://www.last.fm/api/submissions.

The Last.fm API provides applications with a vast set of data that links users with artists, tracks, events, and additional items. It's a unique resource for describing and defining musical taste. Developers can make the most of the Last.fm API by creating music and social-networking applications that deliver new ways to explore and present this data.

Resources:

1. How to consume REST services with WCF, Pedram Rezaei

2. Accessing Web Services in Silverlight, MSDN

   
Steve Apiki is senior developer at Appropriate Solutions, Inc., a Peterborough, NH consulting firm that builds server-based software solutions for a wide variety of platforms using an equally wide variety of tools. Steve has been writing about software and technology for over 15 years.