Default browser script

Here’s a quick little Python script for getting the default browser on a Mac. It’s the sort of thing that can be useful in an AppleScript,

set home to POSIX path of (path to home folder)
set defaultBrowser to (do shell script home & "bin/default-browser")
tell application id defaultBrowser 
  [blah blah blah]
end tell

or in an open command when you want to force a non-HTML file to open in your browser,

db=`~/bin/default-browser`; open -b $db file.txt

John Gruber has used Perl and its Mac::InternetConfig library to do this sort of thing, but I don’t want to use Perl and I especially don’t want to use a library named after a utility I used back in the System 7 and 8 days.1

Your default browser is one of the many pieces of information kept in the Launch Services property list file, which is at

~/Library/Preferences/com.apple.LaunchServices.plist

You need to open that file, search through it to find the http entry, and get its bundle identifier. Here’s the script that does it, which I call default-browser and keep in my ~/bin directory.

python:
 1:  #!/usr/bin/python
 2:  
 3:  from plistlib import readPlist
 4:  from os import environ, remove
 5:  from shutil import copy
 6:  from tempfile import mkstemp
 7:  from subprocess import call
 8:  
 9:  # Copy the original Launch Services preferences to a temporary file.
10:  f = environ['HOME'] + "/Library/Preferences/com.apple.LaunchServices.plist"
11:  (handle, tf) = mkstemp(suffix='.plist', dir=environ['HOME'])
12:  copy(f, tf)
13:  
14:  # Convert the binary plist to an XML plist.
15:  call(['plutil', '-convert', 'xml1', tf])
16:  
17:  # Read through the plist and pluck out the default browser.
18:  pl = readPlist(tf)
19:  for i in pl['LSHandlers']:
20:    if ('LSHandlerURLScheme' in i) and i['LSHandlerURLScheme'] == 'http':
21:      print i['LSHandlerRoleAll']
22:      break
23:  
24:  # Delete the temporary file.
25:  remove(tf)

Python has a nice plistlib library that knows how to read a property list file and turn it into a Python dictionary. Unfortunately, the library seems to work only on property lists that are stored as XML files, and the Launch Services plist is stored in binary format.

To get around this problem, we create a temporary file (Line 11), copy the binary plist to it (Line 12), and then convert the copy from binary to XML through the built-in plutil command (Line 15). Then we can search through the dictionary entry to find the handler associated with the http protocol (Lines 18-22).2

The Python tempfile library has some methods that create self-destroying file objects, but since we need a real file to run plutil on, we had to use the mkstemp method, which doesn’t clean up after itself. Thus, the file deletion on Line 25.

The output of default-browser is a bundle identifier, one of those things that looks like a backward domain name. For the three most popular browsers, the identifiers are

Browser Bundle ID
Safari com.apple.safari
Chrome com.google.chrome
Firefox org.mozilla.firefox

If you want to write scripts that work under different browsers, a utility like default-browser can be handy.


  1. There’s a Python library with essentially the same name, and I don’t want to use it, either. 

  2. How did I know the names of the dictionary keys? I opened the plist file in XCode and looked through it for the names.