lindner (lindner) wrote,

On Vox: Windows Live API, better than page scraping

So we use this toolkit from Octazen to scrape contact lists off of various sites.  Our ever eager users (ab)used this feature so much that hotmail blocked us.

So I waded through reams of API docs over at and finally came up with this prototype perl script to talk to their API servers.  Gets the job done for now.  Will want to rewrite it in native Java and add decent error handling soon.  Hopefully this post here will help other folks needing to talk to Live API:

# Output tab separated values for a given hotmail username/password
# Implementation of Windows Live Contacts API
# Uses RPS authentication described here:

use HTTP::Request;
use LWP::UserAgent;

my $username = shift || die "Need a username\n";
my $password = shift || die "Need a password\n";
my $apikey = 'YOURAPIKEY';

my $ua = LWP::UserAgent->new;

my $uri = '';
my $req = HTTP::Request->new(POST => $uri);
my $xml = <<EOF
    xmlns:s = ""
    xmlns:wsse = ""
    xmlns:saml = "urn:oasis:names:tc:SAML:1.0:assertion"
    xmlns:wsp = ""
    xmlns:wsu = ""
    xmlns:wsa = ""
    xmlns:wssc = ""
    xmlns:wst = "">
        <wlid:ClientInfo xmlns:wlid = "">
        <wsa:Action s:mustUnderstand = "1"></wsa:Action>
        <wsa:To s:mustUnderstand = "1"></wsa:To>
            <wsse:UsernameToken wsu:Id = "user">
        <wst:RequestSecurityToken Id = "RST0">
            <wsp:PolicyReference URI = "MBI"></wsp:PolicyReference>

$req->content_length(length $xml);

my $res = $ua->request($req);

# Ugly way of hacking out the binarysecuritytoken
my $resultxml = $res->content();
$resultxml =~ m,<wsse:BinarySecurityToken[^>]*>(.*)</wsse:BinarySecurityToken>,si;
my $binarytoken = $1;

# Request contacts
my $contactsurl = "$username/LiveContacts/Contacts";
my $authheader = 'WLID1.0 t="' . $binarytoken . '"';
my $contactsreq = HTTP::Request->new(GET => $contactsurl, ['Authorization' => $authheader]);

my $contactres = $ua->request($contactsreq);
my $contactxml = $contactres->content();

use XML::Simple;
my $result = XMLin($contactxml, 'ForceArray' => ['Email', 'Contact']);

# parse emails
foreach my $c (@{$result->{'Contact'}}) {
    my $fname = $c->{Profiles}->{Personal}->{FirstName};
    my $lname = $c->{Profiles}->{Personal}->{LastName};
    foreach my $a (@{$c->{Emails}->{Email}}) {
        print "$fname\t$lname\t" . $a->{Address} . "\n";

Originally posted on


  • Post a new comment


    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 1 comment