Learn how to create PDF documents from scratch with PDFBox: add pages, write text with standard or embedded fonts, draw images and vector shapes, and control page size.
Use this file to discover all available pages before exploring further.
PDFBox lets you create PDF documents entirely in Java — from a single blank page to multi-page documents with formatted text, embedded images, and vector graphics. The core classes are PDDocument, PDPage, and PDPageContentStream.
A valid PDF must contain at least one page. Use PDDocument as a try-with-resources block so the document is always closed after saving.
1
Create a PDDocument and add a page
CreateBlankPDF.java
import org.apache.pdfbox.pdmodel.PDDocument;import org.apache.pdfbox.pdmodel.PDPage;try (PDDocument doc = new PDDocument()){ // a valid PDF document requires at least one page PDPage blankPage = new PDPage(); doc.addPage(blankPage); doc.save("blank.pdf");}
2
Save and close
Call doc.save(filename) before the try-with-resources block exits. The close() call is handled automatically. Never call save() after close().
PDDocument implements Closeable. Always use try-with-resources or call close() explicitly to release file handles and memory.
Use PDPageContentStream to draw text onto a page. You must call beginText() before writing and endText() when finished. Coordinates are in points measured from the lower-left corner of the page.
Use AppendMode.APPEND to add content without overwriting the existing page stream. Pass true for the resetContext parameter when appending to an existing stream to avoid inheriting the page’s graphics state:
newLineAtOffset(x, y) moves the text position relative to the start of the current line. To position text absolutely on the page, use setTextMatrix(Matrix.getTranslateInstance(x, y)).
Load an image from a file with PDImageXObject.createFromFile(), then draw it onto the page with drawImage(). Coordinates refer to the lower-left corner of the image.
AddImageToPDF.java
import org.apache.pdfbox.Loader;import org.apache.pdfbox.pdmodel.PDDocument;import org.apache.pdfbox.pdmodel.PDPage;import org.apache.pdfbox.pdmodel.PDPageContentStream;import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode;import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;try (PDDocument doc = Loader.loadPDF(new File("input.pdf"))){ PDPage page = doc.getPage(0); // createFromFile is the easiest way with an image file // if you already have the image in a BufferedImage, // call LosslessFactory.createFromImage() instead PDImageXObject pdImage = PDImageXObject.createFromFile(imagePath, doc); try (PDPageContentStream contentStream = new PDPageContentStream( doc, page, AppendMode.APPEND, true, true)) { float scale = 1f; contentStream.drawImage(pdImage, 20, 20, pdImage.getWidth() * scale, pdImage.getHeight() * scale); } doc.save("output.pdf");}
If you already have the image as a BufferedImage in memory, use LosslessFactory.createFromImage(doc, bufferedImage) instead of createFromFile.
PDFBox includes constants for common page sizes in PDRectangle. Pass the rectangle to the PDPage constructor to set the size.
import org.apache.pdfbox.pdmodel.common.PDRectangle;// Portrait A4PDPage pageA4 = new PDPage(PDRectangle.A4);// Portrait US LetterPDPage pageLetter = new PDPage(PDRectangle.LETTER);
Common PDRectangle constants: A0–A6, LETTER, LEGAL, TABLOID. You can also construct a custom size:
Custom page size
// Custom 6×4 inch page (1 point = 1/72 inch)PDPage custom = new PDPage(new PDRectangle(6 * 72, 4 * 72));
PDPageContentStream exposes path construction operators (moveTo, lineTo, addRect) and painting operators (stroke, fill). This example draws a rectangle around text from CreateLandscapePDF.java:
To draw a filled rectangle in a single call, use addRect followed by fill:
Filled rectangle
// x, y, width, height — origin is lower-leftcontentStream.addRect(50, 50, 200, 100);contentStream.fill();
Each path segment built with moveTo/lineTo must be painted with stroke() or fill() before starting a new path, or the operators will be applied to the combined path.