Custom Homescreen Icons with Pythonista

Back in the day, when there was no iPhone SDK, you could already add web apps to your homescreen – basically glorified bookmarks that could specify their own icon and look (more or less) like a native app. Unfortunately, not all websites specify a proper apple-touch-icon, and sometimes you end up with a static screenshot instead. You also can't override the website's preference of whether it's launched in full-screen mode (without Safari's UI) or not.

Another limitation of these Safari "webclips" is that you can only use them to launch web (i.e. http[s]) URLs, not mailto:, tel:, maps:, or any of the myriads of third-party app URL schemes.

However, there's one other way of adding webclips to your homescreen: You can install configuration profiles from a web page, or using the iPhone Configuration Utility. Icons that are installed with configuration profiles can override the website's icon and full-screen settings, and it's also possible to use custom URL schemes.1

The iPhone configuration utility is pretty easy to use, but it obviously requires that you have a Mac or PC at hand. It would be easy to write a web app that allows you to create/download custom configuration profiles2, but I wanted to see if I could do it just using Pythonista, without requiring an internet connection.3

After a little bit of tinkering with the iPhone Configuration Utility, plistlib and BaseHTTPServer, I came up with this script:

→ [GitHub]

Here's how it works:

  • Using a few Pythonista-specific functions from the console and photos modules (that would also work in Editorial), it requests a title, URL, and icon (picked from the camera roll) for the shortcut icon.

  • From these things, it generates an xml plist file that contains the configuration profile (using plistlib for generating xml and PIL for encoding the image data). I used a profile that I generated with the iPhone Configuration Utility as a template.

  • Then, a local web server is started, so that Safari can access the file. Local servers are a mechanism of inter-app communication that is rarely used, but works just fine. The server could only run for 10 minutes in the background, but for our purposes, that's more than enough, and in this case, it actually stops after serving one request.

  • Using the webbrowser module, we switch to Safari, pointing it to the URL of the local web server.

  • After downloading the profile from our local server (which then stops serving requests), Safari switches to the Settings app, where an installation dialog is shown. When you tap the "Install" button, you have a new icon on your homescreen.


I can think of a couple of use cases for this:

  • Use a custom icon for a web app if you don't like its default one (or it doesn't specify an icon at all).

  • Launch a web app in full-screen mode that normally wouldn't (I find this especially useful for some shops, like Audible).

  • Dial a contact's number (using a tel: URL) or create a new email (mailto:) by tapping on the photo of a person (the icon is cropped/resized automatically, so you don't have to create a square image first).

  • Launch a Pythonista script directly from the home screen, or open an often-used document in Editorial.

  • Open the maps app with navigation directions to a favorite location, perhaps using a Maps screenshot or a photo as the icon.

One thing to keep in mind with these configuration profiles is that they can clutter the Settings app. When you remove the icon from the homescreen, the profile is not removed automatically, so you might want to clean up the "Profiles" section from time to time (under "General").

  1. One caveat: A white screen is shown briefly before iOS launches the actual URL. Custom URL schemes also didn't work in iOS 7.0, but this has been fixed with 7.0.3. 

  2. I haven't done any research, but I'm sure something like this already exists. 

  3. There are also some privacy concerns when using a web app because some custom URLs can contain sensitive data (e.g. tel: URLs with private phone numbers).