web: automating bits of Sprint Picture Mail

(The good programmer is lazy; instead of typing something over and over, she writes a script to automate the steps. The wizard programmer writes a set of object classes that model the problem at hand, and tells those objects to behave. The genius programmer writes a new language suitable for the problem domain.)

I wanted to automate getting info about my pictures from the soon-to-be-discontinued Sprint Picture Mail website.

The script so far

  1. Login at the  special log-in URL http://pictures.sprintpcs.com/downloadmymedia
  2. In a new tab, visit http://pictures.sprintpcs.com/ajax/view/getAlbumListResults.do?sortCode=5 which should produce a lot of [ {"panel":"albums", "url":  ..., stuff.
  3. Select the entire following one-line bookmarklet, copy it, switch back to the tab in  your browser where the [{“panel” blah blah stuff is, paste it into the location field, then press [Enter].
javascript:var linkWin=open("","albums","width=400,height=600,scrollbars,resizable"),lw=linkWin.document,isJSON=!0;try{albums=JSON.parse(document.body.innerHTML.replace(/\\'/,"'"))}catch(e){isJSON=!1}if(isJSON&&typeof albums=="object"&&Array.isArray(albums)&&albums.length>0){baseURL=document.baseURI.match(/(.*?\/\/.*?)\//)[1],lw.write('<base href="'+baseURL+'" target="_blank">\n'),lw.write("<ol>\n");for(i=0;i<albums.length;i++){var album=albums[i];lw.write("  <li>"+album.title.link("/ui-refresh/getMediaContainerJSON.do?componentType=mediaDetail&sortCode=17&containerID="+album.containerID)+" - "+album.coverTitle+"</li>\n\n")}lw.write("</ol>\n")}else lw.write("<p>window contents do not appear to be Sprint Picture Mail JSON info</p>\n"),lw.write('<p>Try visiting <a href="http://pictures.sprintpcs.com/ajax/view/getAlbumListResults.do?sortCode=5">http://pictures.sprintpcs.com/ajax/view/getAlbumListResults.do?sortCode=5</a></p>\n');

(If you want to read the code, here’s the original un-uglified easier-to-read version.) This should pop up a new browser window that either lists your Picture Mail albums, or tells you what to do.

Then for each album,

  • right-click the link and Save Link As.. Album name.json. This file contains details for each picture in the album (description, creationDate, etc.)
  • If it’s got less than 50 pictures and videos combined, then back in your SPM tab, drag the album’s thumbnail into ‘Download to my PC’

Bookmarklet background

Once you’re logged in to SPM, a bookmarklet can modify the contents of a web page to do something useful.

Googling found a suitable bookmarklet half-way down a page of bookmarklets from 2003:


Copy and paste this babble into your location bar and press enter, and it pops up a new window that lists all the URLs on a page!

It’s hard to read because a bookmarklet is a URL, just like http://example.com/path but starting with javascript: , so it has to be a single line. First thing to do is to find a tool to convert between compressed rubbish and a decent multi-line program… UglifyJS. Yay, more tools in JavaScript, it’s taking over the world.

npm install uglify-js
sed 's/javascript://' < pcreview_bookmarklet \
  | ./node_modules/uglify-js/bin/uglifyjs -b \
  > spm.js

Now I’ve got a multi-line JavaScript file. To turn this back into a bookmarklet,

./node_modules/uglify-js/bin/uglifyjs spm.js \
   | sed 's/^/javascript:/'

I then paste the contents of the resulting single-line JavaScript into my browser’s location bar; to automate this step, pipe it into a clipboard utility such as xsel -b.

Now, to do the coding…

Generating an album list

Once logged in, a useful URL to visit is http://pictures.sprintpcs.com/ajax/view/getAlbumListResults.do?sortCode=5

this returns a JSON structure of all my picture albums. To parse it, just


this fails! Sprint took the title of one album, 2512 house (DL’d!), and turned it into

"title": "2512 house (DL\'d!)"

but this is invalid JSON, you don’t put a backslash in front of single quote.

OK, so

albums=JSON.parse(document.body.innerHTML.replace(/\\'/, "'"));

Now iterate through this, for each album fabricate

  1. a  link to its details
  2. and if it has fewer than 50 pictures, a link to download it.

The first is easy, since my research found the URL that returns the album detail is just /getMediaContainerJSON.do?componentType=mediaDetail&sortCode=17&containerID=MMMMMMMM)

The second is much harder, as SPM seems to fabricate a hidden form that enumerates the elementIDs and extensions of pictures to download, and then dynamically modifies this to turn it into a POST to a /downloadzip/sprintpictures.zip?machineid=xxxx URL. This is hard to do with a bookmarklet.

Parsing an album’s media details

Once you’ve saved an album’s details as Album name.json  you want to walk the structure looking for interesting info and warning about unexpected values. You could do this in another browser bookmarklet, but I want to change the names and modification times of files based on the info, and you can’t perform those operations in browser JavaScript. But the nice node.js engine can. The script is here.

Attempts  to trigger downloads

Getting album and picture metadata is nice, but the most time-consuming part is selecting and dragging albums and pictures to [Download to my PC].

I started writing a bookmarklet that would make SPM’s download form’s hidden form fields visible and label them, so you could then fill it with your own element IDs and drive your own arbitrary download. But you’d have to interactively step in to provide the machine ID, download URL, etc.

It would be better to do it by driving the whole process from node.js. The script takes a login and password, supplies them in a request to some SPM login URL, then remember cookies sent back by SPM and uses them in subsequent requests. Useful links for this: How to POST in node.js, logging in with cookie.

But I can’t figure out SPM login, it’s a bear. Their login form’s <noscript> action is to call authenticate.jsp, but instead it does an AJAX in-page call to a different login URL, which returns script to check if cookies are enabled and then redirects. I tried both URLs using curl and node.js and even though I get a pmjsessionid cookie back, my subsequent requests fail. SPM must be looking for user agent or a particular sequence of requests, or something else. Help wanted!

To Dos

These kinds of explorations reveal shortcomings in the source material. In an open source read-write web, you can fix them:

  • Rewrite the Wikipedia bookmarklet article: “it has been found that passive voice is to be avoided”, also you can just paste the code in without creating a bookmark
  • File an issue for UglifyJS to support a –bookmarklet option to prepend javascript: .
  • UglifyJS needs a –help arguments option.
  • So why isn’t node.js built in to my browser? It’s all JavaScript.

About skierpage

As you might guess, my site is mine. My Schema.org info is at .
This entry was posted in software, web. Bookmark the permalink.

2 Responses to web: automating bits of Sprint Picture Mail

  1. So refreshing to find your site. I am older and don’t fully understand what you write but I have to download 7,000 pictures off my Sprint site by June 17, to an older Mac, but preferably to my WD external hard drive.

    Am trying to BULK DOWNLOAD and keep the meta data for later organizing. Any suggestions? Know anybody I can hire to do this? I too only saw the discontinuation announcement recently!

    (617) 308-5281 (mobile/text)

    PS Sprint customer service is worse than useless.

  2. skierpage says:

    Hey Allan,

    I never found a substitute for a whole lot of clicking and dragging (summarized near the top of my other post under “Downloading the images”).

    But if you follow the steps under “The script so far” in this post, you can save the metadata for each of your albums (primarily the upload date and description of each picture) before SPM goes away, and I should be able upload another bookmarklet to show it to you.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.