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. Hey, so... this is almost working for me, except that the print center is just looping between starting the job and trying to send it, and nothing is getting printed. I set this up on my Ubuntu box, and its trying to point to a Brother Printer which is actually hooked up to a Windows computer through a MacBook.. i think that complexity could have something to do with the failure though.

    AirPrint Brother HL-5140 @ %h

    ty=Brother HL-5140 series CUPS
    note=Main Room
    product=(HL-5140 series)

  2. It might be because the printer is on another computer (different than the one you're advertising). You will have to add / edit the "host-name" in your new service to point to the printer or computer.

  3. Nope, I set up a local PDF virtual printer and tried sharing it with no luck (using cups-pdf) the iPad just flicks between "status | Waiting" and "status | Printing 1 of 2..." with no effect. It looks to me like its having trouble connecting to my ubuntu desktop.. but i've got printer sharing turned on so far as i can tell.

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

    God bless you! :-D

  5. @steven, make sure you've actually gone and configured your cupsd.conf file. The vanilla copy won't work for this. You definitely need ServerAlias * to be in there and then some other stuff might be needed

  6. Didn't work for me, running ubuntu 10.4. Looks like it works from the iPhone side, but nothing ever gets into the print queue. CUPS access log shows a Get-Printer-Attributes call with a 200 success, but just one line (from an ipv6 origin). When I print from a windows machine (to the same cups printer) I see many more lines in the access log with an ipv4 origin. lpr sample.pdf works fine. tj's script worked fine. What else can I check, look into?

  7. Works great(iPad-> Debian and MacBook -> Debian) , but the print job sure takes a long time to start. As far as I can tell the delay is on the client side (tcpdump shows no traffic on the Debian side). Anyone else having the same issue?

  8. Canot run python script :(

    "Failed to find python libxml or elementtree"

    Can someone help - or maybe if you have the service file for Canon Pixma iP5300?

  9. Does AirPrint only use multicast mDNS or also Unicast DNS-SD? We're trying to make it work on an enterprise network without allowing broadcasts across subnets.

  10. Thanks very much for the article and to the people who suggested adding the ServerAlias * to cups.conf. Did that and I could print!

  11. How Conserns

    Manually adding DNS-SD printer service discovery records for AirPrint to an existing name server.


    _universal._sub._ipp._tcp PTR prn._ipp._tcp
    _ipp._tcp PTR prn._ipp._tcp
    prn._ipp._tcp SRV 0 0 631 cups..tld.
    TXT "URF=none" "txtvers=1" "qtotl=1" \
    "rp=printers/" \
    "ty=Fiery X3eTY 35C-KM PS Color Server v2.01 eu" \
    "product=(Fiery X3eTY 35C-KM PS v2.01 eu)" \
    "transparent=t" "copies=t" "duplex=t" "color=f"\
    "pdl=application/pdf,application/postscript" \
    "note=Campus, Building, Floor, Hall"

    Regards Peter

  12. Hi,

    thanks a lot very usefull tutorial, i have my debian with cups 1.3.8 and avahi now printing on my samsung ML-2010 from the iphone. I don't understand how to protect the printer with login and password the txt record "air=username,password" when used put a lock icon on the printer when listed in the iphone but no credentials are asked when printing. Anyone used this record with succes?



  13. Does this still work on 4.3? I've tried this (and airprint for windows) and both come up with "No Printers Found" even though i see MDNS standard query coming from iphone/ipad and MDNS Standard query Response.

    No idea why it won't work (linux cups or windows airprint.exe).


  14. FYI.. those responses are in Wireshark (sniffer). Phone is asking, and servers are responding. I never tried this with 4.2.x but 4.3 isn't working right now for me.

  15. Thanks, this blog and tjfontaine's python script made it a breeze to print to my network attached Dell 1700n from my iPad WiFi (1st Gen) w/ iPhone OS 4.3.1 by way of my Ubuntu 10.04.2 LTS box.

  16. Does not work for me either with ios 4.3.2. Worked with ios 4.2.x. Anyone got an idea what is wrong with ios 4.3

  17. I just found out that you need to enable and disable flight mode to reset the WLAN connection. Then the iphone was able to find the printer. It seems that the bonjour service of the device does a complete rescan only if the wlan is freshly activated. Saw some reports of that in different boards.

  18. The only thing I had to change because of my LAN setup is to add the line:
    ServerAlias *
    somewhere in /etc/cups/cupsd.conf Otherwise I got bad request errors bevause the iPad used a server name that cups refused to validate. Certainly due to my LAN setup. Hope this could help some of you.


    1. I had the same problem. Once I added "ServerAlias *" to the top of my /etc/cups/cupsd.conf file, it started to work.

      I also used the script provided in the first comment to generate my service file. It wouldn't work initially. In case anybody else gets stuck, I had to install python-cups before running the script.

  19. Thank you very much for these instructions. They helped me to patch the CUPS packages in Ubuntu Natty (11.04, will come with next update) and Oneiric (11.10) to automatically advertize printers via DNS-SD in a way to be found and accepted by AirPrint clients, without any additional service definition file. You only need to share your printers. See


  20. Hey everybody,

    first of all: thank you very much, it's such a great tutorial, everything works fine with my Epson printer. But I plan to share a Virtual PDF Printer working with cups-pdf for my iPad, too.

    My question: I just modified my skript for the Epson and I changed the same fields I did for the Epson with you suggestion above, but my devices still don't find it! I make a new service-file. Is the Problem that avahi only can handle with one file?

    Here is my script for the Virtual PDF-Printer, maybe there a some mistakes, I'm a real Newbie on text-based Linux, sorry ;)

    PDF Printer

    ty=>PDF Printer
    product=PDF Printer

  21. THANK YOU!!! This walk through is awesome, worked right off the bat using an iPod touch, iOS 5 Beta 2, CentOS 5.6 Server & Ricoh Aficio CL3500N Printer!

  22. Ok this is an awesome guide you have here, thank you. One stumbling block I found was that I have firestarter (Ubuntu firewall for dummies) and it was preventing my ipad from seeing the printers. After a lot of messing about I discovered reference to multicast being blocked by firestarter by default. Through trial and error I found this solution:
    1. Edit /etc/firestarter/firewall
    2. Comment out these lines:
    $IPT -A INPUT -s -d 0/0 -j DROP
    $IPT -A INPUT -s 0/0 -d -j DROP
    $IPT -A OUTPUT -s -d 0/0 -j DROP
    $IPT -A OUTPUT -s 0/0 -d -j DROP

    After restarting firestarted I found I could still print, even though the firewall was active. Anyway, thought this tidbit might be helpful to your readers.

  23. Dude, you rock! As a Linux noob, this was easy enough. Now, here it is 2011. Why are we printing?

    1) Kids reports - yes, schools should allow electronic submissions - will probably happen by the time my great grandchildren get to school
    2) Coupons stores need - yes, they should allow e-coupons and scan at the checkout, but most don't
    3) Mailing labels
    4) Recipes - yes I do want a recipe service to submit directly to MasterCook on the PC, but until then...

    Any others?

  24. Can you confirm if this still works on iOS 5? Lots of people are doing the Windows equivalent of this with the utility at They are reporting iOS 5 incompatibility. Some are even saying that AirPrint doesn't work with certain canon and hp printers natively after the ios5 update.

    Since it looks like you have dug further into tracing the protocol, can you tell if Apple changed something for iOS 5? Perhaps something new in the URF header?


  25. Hello ! Thanks for the Great Description . It worked very well since i updated my iPhone to iOS 5.

    Are there any known solutions ?


  26. On IOS5 using Ubuntu 10.04 LTS this works but only if I setup a cron job to touch the appropriate .services file every minute. As soon as the file is touched the printer shows up again. Otherwise it says no airprint printers found. Seems like there might be something with avahi that isn't quite right. Anyone have any ideas?

  27. I just tried this with Ubuntu 11.10 and found that I don't need to create the service file. I'm using IOS5 on my iPod Touch and once I have cups setup to publish, it all just works.

Leave a Reply

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