DEV Community

Allen Yang
Allen Yang

Posted on

How to Add Text Headers and Footers to PDF Using Python

Adding Headers and Footers to PDF Documents Using Python

PDF is the standard format for document distribution and archiving, and headers and footers are an indispensable part of formal documents—elements such as company names, document titles, section information, and page numbers all rely on them. For developers, manually adding headers and footers to a PDF that is dozens or even hundreds of pages long is clearly impractical. When documents need to be generated in batches on a regular basis, a programmatic approach is almost the only viable option.

This article explains how to add headers and footers to PDF documents using Python, covering plain-text headers and footers, image headers, different headers for different pages, and automatic page numbers generated through page templates.

Why Add Headers and Footers Programmatically

Handling PDF headers and footers in code offers several practical advantages over manual editing:

  • Batch Processing — Iterate through all pages with a loop and apply uniform headers and footers to the entire document in a single run
  • Dynamic Content — Elements like page numbers and section numbers can be generated automatically based on the document state, with no manual maintenance required
  • Consistent Styling — Fonts, colors, and alignment are controlled uniformly by code, avoiding the inconsistencies of manual work

Environment Setup

This article uses the Spire.PDF library to process PDF documents. Install it as follows:

pip install Spire.PDF
Enter fullscreen mode Exit fullscreen mode

The library provides complete PDF creation and editing capabilities. Headers and footers are implemented by drawing text, images, and lines on the page canvas. Note that the PDF coordinate system has its origin at the bottom-left corner of the page, and the unit is points (1 point = 1/72 inch).

Adding Text Headers and Footers

To add uniform text headers and footers to an entire document, the most common approach is to iterate through all pages and draw the content on each page's canvas. The following code adds right-aligned header text at the top of every page, and a separator line with page numbers at the bottom:

from spire.pdf.common import *
from spire.pdf import *

doc = PdfDocument()
doc.LoadFromFile("Input.pdf")
margin = doc.PageSettings.Margins

# Define the pen, font, and alignment
pen = PdfPen(PdfBrushes.get_Black(), 0.75)
font = PdfTrueTypeFont("Arial", 12.0, PdfFontStyle.Italic, True)
brush = PdfBrushes.get_Black()
format = PdfStringFormat(PdfTextAlignment.Right)
format.MeasureTrailingSpaces = True
space = font.Height * 0.75

for i in range(doc.Pages.Count):
    page = doc.Pages.get_Item(i)
    x = margin.Left
    width = page.Canvas.ClientSize.Width - margin.Left - margin.Right

    # Header: draw a separator line + text
    y = margin.Top - space
    page.Canvas.DrawLine(pen, x, y, x + width, y)
    page.Canvas.DrawString("Internal Use", font, brush, x + width, y - font.Height, format)

    # Footer: draw a separator line + page number
    y = page.Canvas.ClientSize.Height - margin.Bottom + space
    page.Canvas.DrawLine(pen, x, y, x + width, y)
    label = "{0} / {1}".format(i + 1, doc.Pages.Count)
    page.Canvas.DrawString(label, font, brush, x + width, y + 1, format)

doc.SaveToFile("HeaderAndFooter.pdf")
doc.Close()
Enter fullscreen mode Exit fullscreen mode

Output preview:

Adding text headers and footers to a PDF with Python

A few key points to note:

  • PdfTrueTypeFont specifies the font name, size, and style; PdfFontStyle.Italic means italic, and the last Boolean parameter controls whether the font is embedded
  • PdfStringFormat controls text alignment; setting MeasureTrailingSpaces = True makes right-aligned text account for trailing spaces, ensuring precise positioning
  • The header sits above the top margin and the footer below the bottom margin; font.Height * 0.75 reserves a reasonable gap between the text and the separator line

Inserting Images in Headers

Many documents place a company logo in the header. Images are also drawn on the canvas—load the image with PdfImage.FromFile(), then call DrawImage() to specify where it should be drawn:

headerImage = PdfImage.FromFile("Logo.png")
page.Canvas.DrawImage(headerImage, PointF(0.0, 0.0))
Enter fullscreen mode Exit fullscreen mode

The second parameter of DrawImage() is the coordinate of the image's top-left corner. If you need to control the image size, you can pass additional width and height parameters (in points)—for example, to shrink the logo by half:

page.Canvas.DrawImage(headerImage, 50.0, 20.0,
    headerImage.Width / 2.0, headerImage.Height / 2.0)
Enter fullscreen mode Exit fullscreen mode

Setting Different Headers for Different Pages

Documents with many sections often require a different header for each chapter. Since headers are implemented by drawing on specific pages, you can simply draw different content per page index:

rect = RectangleF(PointF(0.0, 20.0), SizeF(doc.PageSettings.Size.Width, 50.0))

# Page 1: red, bold, center-aligned
font1 = PdfTrueTypeFont("Arial", 15.0, PdfFontStyle.Bold, True)
format1 = PdfStringFormat()
format1.Alignment = PdfTextAlignment.Center
doc.Pages[0].Canvas.DrawString("Chapter 1 Overview", font1, PdfBrushes.get_Red(), rect, format1)

# Page 2: black, regular, left-aligned
font2 = PdfTrueTypeFont("Arial", 15.0, PdfFontStyle.Regular, True)
format2 = PdfStringFormat()
format2.Alignment = PdfTextAlignment.Left
doc.Pages[1].Canvas.DrawString("Chapter 2 Implementation", font2, PdfBrushes.get_Black(), rect, format2)
Enter fullscreen mode Exit fullscreen mode

Here, doc.Pages[index] is used to access a specific page directly, and each page can then be given its own font, color, and alignment. If a document has many sections, you can first calculate the page ranges for each chapter and then combine that with a loop for batch drawing.

Managing Headers and Footers with Page Templates

When headers and footers need to apply to all pages of a document and take effect automatically, using a page template (PdfPageTemplateElement) is a more elegant solution. Templates are decoupled from page content and are applied automatically to any pages added later:

from spire.pdf.common import *
from spire.pdf import *

# Create a document and set the page size and margins
doc = PdfDocument()
doc.PageSettings.Size = PdfPageSize.A4()
doc.PageSettings.Margins = PdfMargins(50.0, 50.0, 50.0, 50.0)
pageSize = doc.PageSettings.Size

# Create a header template: draw the logo and a separator line
headerSpace = PdfPageTemplateElement(pageSize.Width, 50.0)
headerSpace.Foreground = False
image = PdfImage.FromFile("Logo.png")
headerSpace.Graphics.DrawImage(image, 50.0, 20.0, image.Width / 2.0, image.Height / 2.0)
pen = PdfPen(PdfBrushes.get_LightGray(), 1.0)
headerSpace.Graphics.DrawLine(pen, 50.0, 45.0, pageSize.Width - 50.0, 45.0)

# Create a footer template: use automatic fields to draw "Page x of y"
footerSpace = PdfPageTemplateElement(pageSize.Width, 50.0)
footerSpace.Foreground = False
footerSpace.Graphics.DrawLine(pen, 50.0, 0.0, pageSize.Width - 50.0, 0.0)
number = PdfPageNumberField()
count = PdfPageCountField()
compositeField = PdfCompositeField(
    PdfTrueTypeFont("Arial", 10.0, PdfFontStyle.Regular, True),
    PdfBrushes.get_Black(), "Page {0} of {1}", [number, count])
compositeField.StringFormat = PdfStringFormat(PdfTextAlignment.Left, PdfVerticalAlignment.Top)
compositeField.Bounds = RectangleF(PointF(50.0, 5.0), SizeF(200.0, 20.0))
widget = PdfGraphicsWidget(compositeField.Ptr)
widget.Draw(footerSpace.Graphics)

# Apply the templates to the top and bottom of the document
doc.Template.Top = headerSpace
doc.Template.Bottom = footerSpace

# Add a page and save
doc.Pages.Add()
doc.SaveToFile("TemplateHeaderFooter.pdf", FileFormat.PDF)
doc.Close()
Enter fullscreen mode Exit fullscreen mode

The key here is the two automatic fields, PdfPageNumberField and PdfPageCountField: they don't store concrete values but are replaced automatically with the current page number and total page count at render time, so there's no need to iterate through pages manually. PdfCompositeField combines multiple fields into a single formatted text string. Setting the template's Foreground property to False places the template content behind the page content, so it never obscures the body text.

Practical Tips

  • Preserve existing page content: Drawing headers and footers directly onto existing pages can overwrite the body text. You can first save the original page as a template with page.CreateTemplate(), draw the headers and footers on the new page, and then render the original content to the bottom layer via PdfGraphicsWidget, adding headers and footers without damaging the content.
  • Semi-transparent effects: Calling page.Canvas.SetTransparency(0.5) lowers the opacity of subsequent drawing, letting headers and footers appear in a watermark-like style that is visually softer.
  • Remember font embedding: The last Boolean parameter of the PdfTrueTypeFont constructor controls whether the font is embedded in the document. Setting it to True ensures fonts render consistently when the document is opened on other devices.

Conclusion

This article covered several ways to add headers and footers to PDF documents using Python: drawing text and images on the canvas for custom headers and footers, setting different content per page by page index, and using page templates with automatic fields to manage page numbers uniformly. In practice, you can choose the approach that fits your document structure—simple uniform headers and footers can be done with a drawing loop, while page templates are the more convenient choice when you need automatic page numbers or batch generation.

Once you've mastered these techniques, you can combine them with find-and-replace, watermarks, layers, and other operations to build a complete document automation pipeline.

Top comments (0)