How to print onto virtual letter paper which exists as PDF?

New to the Mac OS X world and with MACs. From the windows world I have a virtual letter paper with my e.g. logo, headers, footers existing as a PDF file.

I would need to be able to universally print onto this existing PDF, as if it were e.g. physically from a printing shop and inserted into my real physical printers paper tray.

Having now looked around in the Apple and MAC world, I kind of lack a way to use that "save pdf" or generate PDF file that is built-in to the OS X operating system itself, but pre-merge and mix it with my vector/pixels of my own supplied PDF virtual letter paper resulting in a nice official document e.g. for business cases and such stuff.

I read about OS X automator and even pdftk and all, and on Windows it is really simple by means for example of a virtual printer.

But on the Apple platform, it seems that there is just no way to put a background (my virtual letter paper coming from my own PDF) properly beneath anything I would like to print, as Apple or any application seems to put white pixels (instead of transparency) when they generate via their own OS X built-in means to generate that PDF.

What am I missing here? What if I wanted to for example print to a blue paper or a green paper as the most simple examples of this use-case? The Apple system or any app(lication) on it, seems to always generate a non-transparent and white-pixeled virtual paper, where my own virtual letter paper cannot compete with and cannot shine through.

Also via the automator I only found ways to stamp onto the saved PDF (thats fine for stamps saying such stuff as specimen, or example, or draft and such things) and printing below (underneath) of the actual document would be kind of near impossible because of that opaque white generated pixels/paper of the OS X system itself.

Also the automator only allows for images/pixel files to be used as stamp ontop/below, and my letter paper comes as PDF / vectorised already.

Is there really no concept on current MAC OS X to mix during the built-in way to generate PDFs with my own pre-defined document / PDF? Or is there no virtual printer driver software which would do this in its own way on the mac platform?

Any existing product for the MAC OS X platform I could buy? Thanks in advance.

  • What product were you using on Windows? Also, do you have the fonts and any graphic image used to create the logo that could be setup in a template document in Pages or Word? Jan 18, 2016 at 19:39
  • I use for example freepdf (formerly freepdfxp) on the windows world. A simple virtual pdf printer and with pdftk from the pdflabs guys it creates beautiful business letters and all. I wouldnt have imagined to have these huge difficulties on the mac osx platform. Yes I can create my letter paper and have all the sources to it, e.g. logo and fonts and layout, only I dont want to create templates for all the applications (if they support template idea in the first place). Thats why the windows solution with the universal virtual printer driver is suitable for any app that can print. Thanks.
    – amacnewbie
    Jan 18, 2016 at 21:06
  • What normally do you use that virtual printer to do, like actual examples? I'm having a hard time imagining why you would need to have a blue background for lots of different things. Well I mean, you could print your document to PDF and then use PhotoShop or Preview or something to overlay your letterhead over that. Or you could use Pages or Word to make a flyer where the background color is a large blue background layer you add.
    – kal-al
    Jan 18, 2016 at 21:12
  • There is for example also the need to print from Excel on OS X onto that virtual letter paper, and Excel can also put background imagery into its cells basically, only it cannot fit it to the whole paper, the margins and borders are not printable with cells thus I cannot put a background there that way if I would create templates for all the different applications that support templates and backgrounds themselves. With a virtual printer with a virtual paper ready to be mixed into the content that is supposed to be printed onto it. This is what the windows platform is capable of.
    – amacnewbie
    Jan 19, 2016 at 7:40
  • Maybe pdftk even on OS X comes handy after all after I have experimented with it some more. Apparently there is pdftk installable version of elcapitan discussed at: stackoverflow.com/a/33248310 and in command line terminal it can do: pdftk infile.pdf background digitalletterpaper.pdf output outfile.pdf Now I am wondering how I can access the generated pdf of the OS X system itself in automator which it offers in all printing dialogs as save pdf or what its called. Any automator or apple script gurus around? Thanks.
    – amacnewbie
    Jan 19, 2016 at 14:15

1 Answer 1


The following python script will Merge one 'template' PDF onto the pages of any PDF file created in the Print dialog. You will need to supply the filepath to the template PDF in the script, then save it in your user Library, inside a folder called "PDF Services" e.g. ~/Library/PDF Services. (This may need to be created, if not already there.)

The script can then be called from the PDF button of the print dialog.


# Merge v. 0.1
# Merges two PDFs 

import sys
import os
import Quartz as Quartz
from Foundation import NSURL, kCFAllocatorDefault
from AppKit import NSSavePanel, NSApp

# Change this filepath to the PDF you want to use a letterhead / template:
watermark = os.path.expanduser("/System/Library/Assistant/UIPlugins/FMF.siriUIBundle/Contents/Resources/person.pdf")
destination = os.path.expanduser("~/Desktop") # Default destination
suffix = " wm.pdf" # Use ".pdf" if no actual suffix required.


def save_dialog(directory, filename):
    panel = NSSavePanel.savePanel()
    panel.setTitle_("Save PDF booklet")
    myUrl = NSURL.fileURLWithPath_isDirectory_(directory, True)
    ret_value = panel.runModal()
    if ret_value:
        return panel.filename()
        return ''

# Loads in PDF document
def createPDFDocumentWithPath(path):
    return Quartz.CGPDFDocumentCreateWithURL(Quartz.CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, path, len(path), False))

# Creates a Context for drawing
def createOutputContextWithPath(path, dictarray):
    return Quartz.CGPDFContextCreateWithURL(Quartz.CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, path, len(path), False), None, dictarray)
# Gets DocInfo from input file to pass to output.
# PyObjC returns Keywords in an NSArray; they must be tupled.
def getDocInfo(file):
    pdfURL = NSURL.fileURLWithPath_(file)
    pdfDoc = Quartz.PDFDocument.alloc().initWithURL_(pdfURL)
    if pdfDoc:
        metadata = pdfDoc.documentAttributes()
        if "Keywords" in metadata:
            keys = metadata["Keywords"]
            mutableMetadata = metadata.mutableCopy()
            mutableMetadata["Keywords"] = tuple(keys)
            return mutableMetadata
            return metadata

def main(argv):
    (title, options, pathToFile) = argv[:]
    shortName = os.path.splitext(title)[0]
    # If you want to save to a consistent location, use:
    # writeFilename = os.path.join(destination, shortName + suffix)
    writeFilename = save_dialog(destination, shortName + suffix)
    shortName = os.path.splitext(pathToFile)[0]
    metaDict = getDocInfo(pathToFile)
    writeContext = createOutputContextWithPath(writeFilename, metaDict)
    readPDF = createPDFDocumentWithPath(pathToFile)
    mergePDF = createPDFDocumentWithPath(watermark)
    if writeContext != None and readPDF != None:
        numPages = Quartz.CGPDFDocumentGetNumberOfPages(readPDF)
        for pageNum in xrange(1, numPages + 1): 
            page = Quartz.CGPDFDocumentGetPage(readPDF, pageNum)
            mergepage = Quartz.CGPDFDocumentGetPage(mergePDF, 1)
            if page:
                mediaBox = Quartz.CGPDFPageGetBoxRect(page, Quartz.kCGPDFMediaBox)
                if Quartz.CGRectIsEmpty(mediaBox):
                    mediaBox = None         
                Quartz.CGContextBeginPage(writeContext, mediaBox)   
                Quartz.CGContextSetBlendMode(writeContext, Quartz.kCGBlendModeOverlay)
                Quartz.CGContextDrawPDFPage(writeContext, page)
                Quartz.CGContextDrawPDFPage(writeContext, mergepage)
        del writeContext
        print "A valid input file and output file must be supplied."

if __name__ == "__main__":

Currently, this uses the first page of the template PDF file and puts it on all pages of the output PDF.

The first line of the script must be a path to an actual python. env` doesn't work in PDF Services, in Sonoma, at least.

  • How is one supposed to use the script? Jan 22, 2019 at 12:50
  • Ah. Once it's in the PDF Services folder, it will appear in the PDF button of the print menu. I'll add that crucial fact to the answer!
    – benwiggy
    Jan 22, 2019 at 13:16
  • 1
    Does not work anymore
    – bora89
    May 16, 2023 at 6:30
  • @bora89 Yes: firstly, Apple has removed python from the OS, so you have to install one yourself. Secondly, there are now 'security' issues with trying to save files from a PDF Service that affect some recent OSes. It's not clear whether it's intention or not, as it does cary.
    – benwiggy
    May 16, 2023 at 6:44
  • Updated for python 3.
    – benwiggy
    May 12 at 13:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .