Batch Download iOS App Icons

This site has been in serious need of a redesign for years and a graphic designer friend of mine had the idea of spelling my domain using app icons! I loved this idea but I had a slight lack of letter based app icons to play around with (read: none).

It turns out Apple provides an iTunes Search API which I could use to programmatically access search results for any terms/categories/etc. The major limitation of this API is that it will only return 200 results for a single search term and has no way to specify pagination (so I can’t, for example, get results 200-400 in my request). The only way around this would be to download and parse the entire Enterprise Partner Feed which contains all metadata in the iTunes store. Regrettably, I am not an enterprise partner (yet) so I don’t have access to that data.

The JSON search results specify locations for both 60×60 and 512×512 app icon images. The script I’ve written prompts the user for a comma separated string containing a list of search results. The script will then query the Search API for each of the terms and download the 200 results into a subfolder named by the associated search term. There’s no support for searching in specific categories only or searching the top charts but that functionality would be trivial to add using the API documentation as reference.

Here is a link to all of the “letter icons” I’ve accumulated: (sorry, I only cared about SIDEAP)

I’ve also included the first draft of the new site logo (currently using the 2nd draft as of 8/29/14). If anyone wants to try their hand at another design I’ll give them two million dollars. Don’t forget to grab the source below as well! My apologies for the lack of comments in the code… I’m better than that.

Website Header Prototype A

import urllib2
import json
import os
import shutil
import thread

downloadCount = 0
totalDownloads = 0

# Download a single file
def downloadFile(url, destination):
	global downloadCount
	f = open(destination, 'wb')

	downloadMessage = 'Completed download ' + str(totalDownloads - downloadCount + 1) + '/' + str(totalDownloads)

	downloadCount -= 1


# Icon downloading (multithreaded implementation)
def downloadIcons(searchTerm, results, verbosity):
	global downloadCount

	if verbosity > 0:
		print('Beginning download of ' + str(results) + ' results for search term "' + searchTerm + '"')

	if verbosity > 1:
		print('Sending HTTP request')

	requestString = '' + searchTerm + '&country=us&entity=software&media=software&limit=' + str(results)
	response = urllib2.urlopen(requestString).read()

	if verbosity > 1:
		print('Received HTTP response')
		print('Parsing into JSON')

	responseJSON = json.loads(response)
	resultCount = responseJSON['resultCount']

	if verbosity > 1:
		print('Received ' + str(resultCount) + ' results')

	for i in range(resultCount):
		appDict = responseJSON['results'][i]
		appName = appDict['trackName']
		appIcon60 = appDict['artworkUrl60']
		appIcon512 = appDict['artworkUrl512']
		appIcon60Ext = appIcon60[appIcon60.rindex('.'):]
		appIcon512Ext = appIcon512[appIcon512.rindex('.'):]

		appName = appName.replace('/', ' ')

		if verbosity > 0:
			print('Downloading App "' + searchTerm + '" ' + str(i + 1) + '/' + str(resultCount))

		if verbosity > 1:
			print('\tName: ' + appName)
			print('\tIcon 512x512: ' + appIcon512[appIcon512.rindex('/') + 1:])

		targetDir = 'Icons/' + searchTerm + '/'

		downloadCount += 1

		thread.start_new_thread(downloadFile, ((appIcon512, targetDir + appName + '512x512' + appIcon512Ext)))

		if verbosity > 1:
			print ('\t\tDownloaded!\n')

# Main function
if __name__ == '__main__':
	if not os.path.isdir('Icons'):

	while (True):
		searchTerm = raw_input('Please enter the search terms seperated by commas (! to exit): ')
		if searchTerm == '!':

		searchTermList = searchTerm.split(',')

		threadedTerms = []

		for term in searchTermList:
			targetDir = 'Icons/' + term

			if os.path.isdir(targetDir):
				userResponse = raw_input('Icons for search term "' + term + '" have already been downloaded... Redownload (y/n)? ')
				if userResponse == 'n':




		for term in threadedTerms:
			totalDownloads += 200
			thread.start_new_thread(downloadIcons, (term, 200, 0))

		wait = raw_input()


Leave a Reply

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