AirPrint and Linux

I've been trying the iPhone OS[1] 4.2 GM, and decided to play with the AirPrint functionality. However, Apple has removed the ability to print to locally attached PC/Mac printers with the final versions of iTunes 10.1 and OS X 10.6.5. Using a beta version of iTunes 10.1 for Windows, Wireshark, avahi-discover and a few other tools, I managed to get an understanding of how AirPrint works. What I've found is:

  • AirPrint uses IPP for print management.
  • AirPrint listens to mDNS (Bonjour/Avahi) for printer discovery.
  • AirPrint requires a _universal subtype to be present in the _ipp announcement before it will consider listing the printer.
  • AirPrint requires an additional TXT record, "URF", to be present and non-empty before it will consider listing the printer.
  • While this URF format (see below) appears to be a future option for Apple, all current AirPrint-enabled apps seem to send print data as PDF.
  • When a printer is protected by a username/password, the iTunes/AirPrint daemon will send a TXT record "air=username,password".

The original announcement as sent by iTunes 10.1 Beta 2 for Windows looked mostly like a normal IPP announcement, except for the _universal subtype (which standard CUPS does not seem to send), and the following TXT records:


(The last record is a literal string "username,password", not an obfuscated user/pass.)

I haven't been able to find much info about what "URF" is. I'm guessing a raster format of some kind. The CUPS implementation in the iTunes beta is accepting it though. What I found is that the image/urf type is not required to be in the pdl record. Currently, all AirPrint enabled apps seem to be fine with sending PDFs, so as long as your CUPS daemon has a PDF filter, you're good. What IS required is the URF record. It has to exist, and cannot be empty, or the printer does not show up in the AirPrint list. The "air" record seems to exist to provide a hint to AirPrint that the target requires a login. If your printer target is not protected by a login, this record can be omitted.

So, with this known, how do we set up a Linux (or presumably *BSD) server as an AirPrint server? We're going to have to manually set up an Avahi service. CUPS can publish to Avahi, but as this requires an extra record and subtype that CUPS does not provide, we'll have to duplicate the printer record manually.

Note that most of this is Debian-centric. If you are not running Debian, you'll probably have to adjust things here and there.

1. Install CUPS and make sure it's actually working. Configuring CUPS correctly is outside the scope of this guide. You will need to have a PDF filter working correctly. Debian seems to provide this out of the box with a CUPS install; your mileage may vary.

2. Go into the CUPS interface and make sure "Share published printers connected to this system" is enabled.

3. Install avahi-daemon and make sure it is running. Restart CUPS to get it to publish printer services. (AirPrint will not be using the CUPS-published services, but we will need them to recreate a manual service.)

4. On another Linux box, install avahi-discover and run it from a terminal. Click the printer you wish to duplicate. Now switch back to the console and a set of debugging lines should be printed similar to this (I've added some linebreaks for readability):

Service data for service 'HP LaserJet 1200 @ nibbler.xn--n3h' of type '_ipp._tcp' in domain 'local' on 3.0:
    Host nibbler.local (, port 631, TXT data: [
        'product=(GPL Ghostscript)',
        'ty=HP LaserJet Series PCL 4/5, 1.3',

5. Back on the server, create /etc/avahi/services/name.service. name can be anything; I named it /etc/avahi/services/hp1200.service in this case.

6. Create an XML file similar to the example below, using the data above as the values. Note that the data is in the opposite order of what avahi-discover gave it to you.

<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<name replace-wildcards="yes">AirPrint hp1200 @ %h</name>
       <txt-record>ty=HP LaserJet Series PCL 4/5, 1.3</txt-record>
       <txt-record>product=(GPL Ghostscript)</txt-record>

The only differences are 1) I named the service "AirPrint hp1200" to not interfere with the "hp1200" service that CUPS publishes, and 2) the added "URF=none" record. And be sure to double check that "application/pdf" is included in the pdl record. If it's not there, don't simply try to add it, that won't work. You'll need to figure out why your CUPS installation doesn't have a PDF filter.

7. Save the file. avahi-daemon should notice the new file and load it without a needed restart.

8. On your iPhone/iPad, go into an application (Safari, for example), print, and search for printers. Your new printer definition should be in there.

9. Print!

10. (Optional) Wonder why you're still printing things in 2010, let alone from a mobile device. For me, this was mostly an exercise in figuring out how AirPrint worked. The example printer used here, an HP LaserJet 1200, was bought used as a demo/display model from an office supply store in 2002. I print maybe 10 pages per year on it. 8 years later, and the original demo toner cartridge is still working fine.


[1] I've been working with Cisco IOS for over 10 years now, and flat out refuse to call this "iOS". Live with it.

63 thoughts on “AirPrint and Linux”

  1. Thanks for this awesome tutorial. I was able to set up my Ubuntu 11.10 server/desktop at home as an AirPrint printer. For the problem where you are seeing the AirPrint printer but cannot print to it, make sure to enable "Share printers connected to this system" in the CUPS administrative screen. The easiest way is to browse to http://localhost:631/admin in the Server/Server Settings section. The option shows up under the "Advanced" link but doesn't require you to go to the advanced settings.

    FYI, my printer is an old-school Brother HL1870N (networked) with BR-Script3. So this is to confirm that the tutorial should work for any attached or non-attached printer.

  2. Hey Ryan, thanx for your work!
    used tjfontaine's script to provide from now on the airprint service from my debian squeeze linux box for ipad and other devices

  3. Airprint and IOS 6 problem

    This link solved the problem for me

    Again thank to all

    Re: iOS 6 doesn't recognize CUPS print shares
    I've made a little bit of progress on this at work, where we're running Debian 6 with CUPS and Avahi-daemon.

    1) Apple changed the format of their airprint printing from PDF to URF with iOS 6.
    2) URF is a unirast format file. This appears to be an apple-specific format
    3) Printers that natively support Airprint have support for URF, so they continue working
    4) CUPS does not natively support unirast, and so the avahi configuration files I generated do not mention that they support URF. Therefore, the Airprint printers do not show up in iOS 6.
    5) Some guy wrote a very basic URF to PDF converter and published it in 2010 when iOS 4.2 came out, because apparently it was necessary then as well.
    6) I've installed this on airprintstaff following these instuctions and re-ran which now mentions URF support
    7) The printers show up under iOS 6 now. The URF format decoding is not complete, though, so the print job must be set to "duplex off" when airprinting. This preference is ignored when the file is converted to PDF anyway (duplex is turned on).

    It looks like URFtoPDF isn't fully developed at this point, but there's definitely a starting point.

    Edit: thanks to previous posters in this thread for assistance in getting this far!
    Last edited by kloostec; 9 Hours Ago at 08:10 PM..

  4. I have a strange behaviour after updating my new ipad to iOS6.
    After the update the new iPad is no more showing any AirPrint printer.
    Another old iPad 1 running iOS 5 (It can't be updated to iOS6... Good bless Apple!!!) it's instead able to show the AirPrintprinter and to print.
    Any idea how to solve the iOS6 problem?

  5. I've setup a CUPS-PDF virtual printer on cups 1.3.11 and printing from Desktop and IPad 1 (iOS 5.1.1) works. But from iPhone 3G (iOS 6.0) getting errors in the cups error log:
    IPP Read Error !
    code=400 (Bad Request)

    Anyone have any ideas ?

Leave a Reply

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