PDFPage
Page class for accessing dimensions, drawing content, and extracting text.
PDFPage
The PDFPage class represents a single page in a PDF document. It provides access to page properties, drawing operations, and text extraction.
const pdf = await PDF.load(bytes);
const page = pdf.getPage(0);
if (!page) throw new Error("Page not found");
console.log(`Size: ${page.width} x ${page.height}`);
console.log(`Rotation: ${page.rotation}`);Properties
ref
The page reference (for low-level operations).
Type: PdfRef (readonly)
dict
The page dictionary (for low-level operations).
Type: PdfDict (readonly)
index
The page index (0-based).
Type: number (readonly)
width
Page width in points (accounting for rotation).
Type: number (readonly)
const width = page.width; // e.g., 612 for US Letterheight
Page height in points (accounting for rotation).
Type: number (readonly)
const height = page.height; // e.g., 792 for US Letterrotation
Page rotation in degrees (0, 90, 180, or 270).
Type: 0 | 90 | 180 | 270 (readonly)
if (page.rotation === 90) {
console.log("Page is rotated 90 degrees clockwise");
}isLandscape
Whether the page is in landscape orientation.
Type: boolean (readonly)
isPortrait
Whether the page is in portrait orientation.
Type: boolean (readonly)
Page Boxes
PDF pages have multiple "boxes" defining different regions. Each returns a Rectangle with { x, y, width, height } properties.
getMediaBox()
Get the MediaBox (page boundary). Falls back to US Letter if not defined.
Returns: Rectangle
getCropBox()
Get the CropBox (visible region). Falls back to MediaBox if not defined.
Returns: Rectangle
getBleedBox()
Get the BleedBox (printing bleed area). Falls back to CropBox if not defined.
Returns: Rectangle
getTrimBox()
Get the TrimBox (intended dimensions after trimming). Falls back to CropBox if not defined.
Returns: Rectangle
getArtBox()
Get the ArtBox (meaningful content area). Falls back to CropBox if not defined.
Returns: Rectangle
setRotation(degrees)
Set the page rotation.
| Param | Type | Description |
|---|---|---|
degrees | 0 | 90 | 180 | 270 | Rotation in degrees |
page.setRotation(90);Text Drawing
drawText(text, options?)
Draw text on the page.
| Param | Type | Default | Description |
|---|---|---|---|
text | string | required | Text to draw |
[options] | DrawTextOptions | ||
[options.x] | number | 0 | X position from left |
[options.y] | number | 0 | Y position from bottom |
[options.font] | string | EmbeddedFont | "Helvetica" | Font to use |
[options.size] | number | 12 | Font size in points |
[options.color] | Color | black | Text color |
[options.opacity] | number | 1 | Opacity (0-1) |
[options.maxWidth] | number | Enable word wrapping | |
[options.lineHeight] | number | size * 1.2 | Line height |
[options.alignment] | "left" | "center" | "right" | "justify" | "left" | Text alignment |
[options.rotate] | Rotation | Rotation options |
// Simple text
page.drawText("Hello, World!", {
x: 50,
y: 700,
size: 24,
color: rgb(0, 0, 0),
});
// With embedded font
const font = pdf.embedFont(fontBytes);
page.drawText("Custom Font", {
x: 50,
y: 650,
font,
size: 18,
});
// Multiline with wrapping
page.drawText(longText, {
x: 50,
y: 600,
maxWidth: 500,
lineHeight: 18,
alignment: "justify",
});Standard 14 Fonts (built-in, no embedding required):
| Font Name |
|---|
"Helvetica" |
"Helvetica-Bold" |
"Helvetica-Oblique" |
"Helvetica-BoldOblique" |
"Times-Roman" |
"Times-Bold" |
"Times-Italic" |
"Times-BoldItalic" |
"Courier" |
"Courier-Bold" |
"Courier-Oblique" |
"Courier-BoldOblique" |
"Symbol" |
"ZapfDingbats" |
Shape Drawing
drawRectangle(options)
Draw a rectangle on the page.
| Param | Type | Default | Description |
|---|---|---|---|
options.x | number | required | X position |
options.y | number | required | Y position |
options.width | number | required | Rectangle width |
options.height | number | required | Rectangle height |
[options.color] | Color | Fill color | |
[options.borderColor] | Color | Border color | |
[options.borderWidth] | number | 1 | Border width |
[options.borderDashArray] | number[] | Dash pattern | |
[options.opacity] | number | 1 | Fill opacity |
[options.borderOpacity] | number | 1 | Border opacity |
[options.cornerRadius] | number | Rounded corners | |
[options.rotate] | Rotation | Rotation |
// Filled rectangle
page.drawRectangle({
x: 50,
y: 500,
width: 200,
height: 100,
color: rgb(0.95, 0.95, 0.95),
});
// Stroked with rounded corners
page.drawRectangle({
x: 50,
y: 350,
width: 200,
height: 100,
borderColor: rgb(0, 0, 0),
borderWidth: 2,
cornerRadius: 10,
});drawLine(options)
Draw a line on the page.
| Param | Type | Default | Description |
|---|---|---|---|
options.start | { x: number, y: number } | required | Start point |
options.end | { x: number, y: number } | required | End point |
[options.color] | Color | black | Line color |
[options.thickness] | number | 1 | Line thickness |
[options.opacity] | number | 1 | Opacity |
[options.dashArray] | number[] | Dash pattern | |
[options.lineCap] | LineCap | "butt" | Line cap style |
page.drawLine({
start: { x: 50, y: 500 },
end: { x: 550, y: 500 },
color: rgb(0, 0, 0),
thickness: 1,
});
// Dashed line
page.drawLine({
start: { x: 50, y: 450 },
end: { x: 550, y: 450 },
dashArray: [5, 3],
});drawCircle(options)
Draw a circle on the page.
| Param | Type | Default | Description |
|---|---|---|---|
options.x | number | required | Center X |
options.y | number | required | Center Y |
options.radius | number | required | Radius |
[options.color] | Color | Fill color | |
[options.borderColor] | Color | Border color | |
[options.borderWidth] | number | 1 | Border width |
[options.opacity] | number | 1 | Fill opacity |
[options.borderOpacity] | number | 1 | Border opacity |
page.drawCircle({
x: 300,
y: 400,
radius: 50,
color: rgb(1, 0, 0),
borderColor: rgb(0, 0, 0),
borderWidth: 2,
});drawEllipse(options)
Draw an ellipse on the page.
| Param | Type | Default | Description |
|---|---|---|---|
options.x | number | required | Center X |
options.y | number | required | Center Y |
options.xRadius | number | required | Horizontal radius |
options.yRadius | number | required | Vertical radius |
[options.color] | Color | Fill color | |
[options.borderColor] | Color | Border color | |
[options.borderWidth] | number | 1 | Border width |
[options.opacity] | number | 1 | Fill opacity |
[options.borderOpacity] | number | 1 | Border opacity |
[options.rotate] | Rotation | Rotation |
page.drawEllipse({
x: 300,
y: 400,
xRadius: 100,
yRadius: 50,
color: rgb(0, 0, 1),
});drawSvgPath(pathData, options?)
Draw an SVG path on the page. Useful for icons, logos, and vector graphics.
| Param | Type | Default | Description |
|---|---|---|---|
pathData | string | required | SVG path d attribute string |
[options] | DrawSvgPathOptions | ||
[options.x] | number | 0 | X position |
[options.y] | number | 0 | Y position |
[options.scale] | number | 1 | Scale factor |
[options.flipY] | boolean | true | Flip Y-axis (SVG to PDF coordinates) |
[options.color] | Color | black | Fill color |
[options.borderColor] | Color | Stroke color | |
[options.borderWidth] | number | 1 | Stroke width |
[options.opacity] | number | 1 | Fill opacity |
[options.borderOpacity] | number | 1 | Stroke opacity |
[options.windingRule] | "nonzero" | "evenodd" | "nonzero" | Fill rule for overlapping paths |
[options.lineCap] | LineCap | Line cap style | |
[options.lineJoin] | LineJoin | Line join style | |
[options.dashArray] | number[] | Dash pattern |
All SVG path commands are supported: M, L, H, V, C, S, Q, T, A, Z (and lowercase relative variants).
// Simple filled triangle
page.drawSvgPath("M 0 0 L 50 0 L 25 40 Z", {
x: 100,
y: 700,
color: rgb(1, 0, 0),
});
// Stroked icon (Lucide-style)
page.drawSvgPath("M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3...", {
x: 50,
y: 600,
scale: 2,
borderColor: rgb(0.9, 0.2, 0.2),
borderWidth: 2,
});
// Path with hole (even-odd fill)
page.drawSvgPath("M 0 0 L 80 0 L 80 80 L 0 80 Z M 20 20 L 60 20 L 60 60 L 20 60 Z", {
x: 200,
y: 500,
color: rgb(0, 0, 1),
windingRule: "evenodd",
});Coordinate System: By default, flipY: true transforms SVG coordinates (Y increases downward) to PDF coordinates (Y increases upward). Set flipY: false when paths are already in PDF coordinate space.
Image Drawing
drawImage(image, options?)
Draw an image on the page.
| Param | Type | Default | Description |
|---|---|---|---|
image | PDFImage | required | Embedded image |
[options] | DrawImageOptions | ||
[options.x] | number | 0 | X position |
[options.y] | number | 0 | Y position |
[options.width] | number | natural | Target width |
[options.height] | number | natural | Target height |
[options.opacity] | number | 1 | Opacity |
[options.rotate] | Rotation | Rotation |
If only width or height is specified, aspect ratio is preserved.
const image = pdf.embedImage(jpegBytes);
// Draw at natural size
page.drawImage(image, { x: 50, y: 500 });
// Scale to width
page.drawImage(image, { x: 50, y: 400, width: 200 });
// With rotation
page.drawImage(image, {
x: 300,
y: 400,
width: 100,
height: 100,
rotate: { angle: 45 },
});Embedded Page Drawing
drawPage(embedded, options?)
Draw an embedded page (Form XObject) onto this page.
| Param | Type | Default | Description |
|---|---|---|---|
embedded | PDFEmbeddedPage | required | Embedded page |
[options] | DrawPageOptions | ||
[options.x] | number | 0 | X position |
[options.y] | number | 0 | Y position |
[options.scale] | number | 1 | Uniform scale |
[options.width] | number | Target width (overrides scale) | |
[options.height] | number | Target height (overrides scale) | |
[options.opacity] | number | 1 | Opacity |
[options.background] | boolean | false | Draw behind existing content |
const watermarkPdf = await PDF.load(watermarkBytes);
const watermark = await pdf.embedPage(watermarkPdf, 0);
// Center on page
page.drawPage(watermark, {
x: (page.width - watermark.width) / 2,
y: (page.height - watermark.height) / 2,
opacity: 0.5,
});
// Draw as background
const letterheadPdf = await PDF.load(letterheadBytes);
const letterhead = await pdf.embedPage(letterheadPdf, 0);
page.drawPage(letterhead, { background: true });Path Drawing
drawPath()
Start building a custom path with a fluent API.
Returns: PathBuilder
// Triangle
page
.drawPath()
.moveTo(100, 100)
.lineTo(200, 100)
.lineTo(150, 200)
.close()
.fill({ color: rgb(1, 0, 0) });
// Complex shape
page
.drawPath()
.moveTo(50, 50)
.curveTo(100, 100, 150, 100, 200, 50)
.lineTo(200, 150)
.close()
.fillAndStroke({
color: rgb(0.9, 0.9, 1),
borderColor: rgb(0, 0, 1),
});PathBuilder Methods:
| Method | Description |
|---|---|
moveTo(x, y) | Move to point |
lineTo(x, y) | Draw line to point |
curveTo(cp1x, cp1y, cp2x, cp2y, x, y) | Cubic bezier curve |
quadraticCurveTo(cpx, cpy, x, y) | Quadratic bezier curve |
appendSvgPath(pathData, options?) | Append SVG path commands |
close() | Close the path |
fill(options) | Fill the path |
stroke(options) | Stroke the path |
fillAndStroke(options) | Fill and stroke |
Using appendSvgPath:
The appendSvgPath method lets you mix SVG path commands with PathBuilder methods:
// Mix PathBuilder methods with SVG path data
page
.drawPath()
.moveTo(50, 500)
.lineTo(100, 500)
.appendSvgPath("l 30 -30 l 30 30", { flipY: false }) // relative SVG
.lineTo(200, 500)
.stroke({ borderColor: rgb(0, 0, 0) });Options for appendSvgPath:
| Option | Type | Default | Description |
|---|---|---|---|
flipY | boolean | false | Flip Y-axis for SVG paths |
scale | number | 1 | Scale factor |
translateX | number | 0 | X translation after transform |
translateY | number | 0 | Y translation after transform |
Note: Unlike drawSvgPath(), the appendSvgPath() method defaults to flipY: false since PathBuilder operates in PDF coordinates.
Low-Level Drawing
For advanced graphics operations, PDFPage provides methods to emit raw operators and register resources. See Low-Level Drawing for detailed usage.
drawOperators(operators)
Emit raw PDF operators to the page content stream.
| Param | Type | Description |
|---|---|---|
operators | Operator[] | Array of operators to emit |
import { ops } from "@libpdf/core";
page.drawOperators([
ops.pushGraphicsState(),
ops.concatMatrix(1, 0, 0, 1, 100, 200),
ops.setNonStrokingRGB(1, 0, 0),
ops.rectangle(0, 0, 50, 50),
ops.fill(),
ops.popGraphicsState(),
]);The caller is responsible for valid operator sequences. Invalid sequences may produce corrupted PDFs.
registerFont(font)
Register a font resource and return its operator name.
| Param | Type | Description |
|---|---|---|
font | EmbeddedFont | Standard14FontName | Font to register |
Returns: string - Resource name (e.g., "F0")
const font = pdf.embedFont(fontBytes);
const fontName = page.registerFont(font);
page.drawOperators([
ops.beginText(),
ops.setFont(fontName, 12),
ops.moveText(100, 700),
ops.showText("Hello"),
ops.endText(),
]);registerImage(image)
Register an image resource and return its operator name.
| Param | Type | Description |
|---|---|---|
image | PDFImage | Embedded image |
Returns: string - Resource name (e.g., "Im0")
const image = pdf.embedImage(imageBytes);
const imageName = page.registerImage(image);
page.drawOperators([
ops.pushGraphicsState(),
ops.concatMatrix(100, 0, 0, 100, 200, 500),
ops.paintXObject(imageName),
ops.popGraphicsState(),
]);registerShading(shading)
Register a shading (gradient) resource and return its operator name.
| Param | Type | Description |
|---|---|---|
shading | PDFShading | Shading resource |
Returns: string - Resource name (e.g., "Sh0")
const gradient = pdf.createAxialShading({...});
const shadingName = page.registerShading(gradient);
page.drawOperators([
ops.pushGraphicsState(),
ops.rectangle(50, 50, 100, 100),
ops.clip(),
ops.endPath(),
ops.paintShading(shadingName),
ops.popGraphicsState(),
]);registerPattern(pattern)
Register a pattern resource and return its operator name.
| Param | Type | Description |
|---|---|---|
pattern | PDFPattern | Pattern resource |
Returns: string - Resource name (e.g., "P0")
import { ColorSpace } from "@libpdf/core";
const pattern = pdf.createTilingPattern({...});
const patternName = page.registerPattern(pattern);
page.drawOperators([
ops.setNonStrokingColorSpace(ColorSpace.Pattern),
ops.setNonStrokingColorN(patternName),
ops.rectangle(100, 100, 200, 200),
ops.fill(),
]);registerExtGState(state)
Register an extended graphics state and return its operator name.
| Param | Type | Description |
|---|---|---|
state | PDFExtGState | Graphics state |
Returns: string - Resource name (e.g., "GS0")
const gs = pdf.createExtGState({
fillOpacity: 0.5,
blendMode: "Multiply",
});
const gsName = page.registerExtGState(gs);
page.drawOperators([
ops.pushGraphicsState(),
ops.setGraphicsState(gsName),
ops.setNonStrokingRGB(1, 0, 0),
ops.rectangle(100, 100, 50, 50),
ops.fill(),
ops.popGraphicsState(),
]);registerXObject(xobject)
Register a Form XObject or embedded page and return its operator name.
| Param | Type | Description |
|---|---|---|
xobject | PDFFormXObject | PDFEmbeddedPage | XObject to register |
Returns: string - Resource name (e.g., "Fm0")
const stamp = pdf.createFormXObject({...});
const stampName = page.registerXObject(stamp);
page.drawOperators([
ops.pushGraphicsState(),
ops.concatMatrix(1, 0, 0, 1, 200, 700),
ops.paintXObject(stampName),
ops.popGraphicsState(),
]);Form Field Drawing
drawField(field, options)
Draw a form field widget on this page.
| Param | Type | Description |
|---|---|---|
field | FormField | Field to draw |
options.x | number | X position |
options.y | number | Y position |
options.width | number | Widget width |
options.height | number | Widget height |
[options.option] | string | Radio option value (required for radio groups) |
Throws:
Error- If field is a signature fieldError- If radio group option is missing or invalid
// Text field
page.drawField(nameField, {
x: 100,
y: 700,
width: 200,
height: 24,
});
// Checkbox
page.drawField(agreeCheckbox, {
x: 100,
y: 650,
width: 18,
height: 18,
});
// Radio group - each option needs its own widget
page.drawField(paymentRadio, {
x: 100,
y: 550,
width: 16,
height: 16,
option: "Credit Card",
});
page.drawField(paymentRadio, {
x: 100,
y: 520,
width: 16,
height: 16,
option: "PayPal",
});Annotations
PDFPage provides methods for adding and retrieving PDF annotations such as highlights, links, sticky notes, shapes, stamps, and freehand drawings.
See the Annotations documentation for the complete API reference.
// Add a highlight
page.addHighlightAnnotation({
rect: { x: 100, y: 700, width: 200, height: 14 },
color: rgb(1, 1, 0),
});
// Get all annotations
const annotations = page.getAnnotations();
// Get specific types
const highlights = page.getHighlightAnnotations();
const links = page.getLinkAnnotations();Text Extraction
extractText(options?)
Extract all text content from the page.
| Param | Type | Description |
|---|---|---|
[options] | ExtractTextOptions | Extraction options |
Returns: PageText
const pageText = page.extractText();
console.log(pageText.text); // Plain text
// Access structured content
for (const line of pageText.lines) {
console.log(`Line at y=${line.baseline}: "${line.text}"`);
}PageText Structure:
interface PageText {
pageIndex: number;
width: number;
height: number;
text: string; // Plain text
lines: TextLine[]; // Structured lines
}
interface TextLine {
text: string;
baseline: number;
spans: TextSpan[];
}findText(query, options?)
Search for text on the page.
| Param | Type | Description |
|---|---|---|
query | string | RegExp | Search query |
[options] | FindTextOptions | |
[options.caseSensitive] | boolean | Case-sensitive matching |
[options.wholeWord] | boolean | Match whole words only |
Returns: TextMatch[]
// String search
const matches = page.findText("invoice");
for (const match of matches) {
console.log(`Found at:`, match.bbox);
}
// Regex search
const placeholders = page.findText(/\{\{\s*\w+\s*\}\}/g);TextMatch Structure:
interface TextMatch {
text: string;
pageIndex: number;
bbox: { x: number; y: number; width: number; height: number };
}Types
Rectangle
interface Rectangle {
x: number; // Left x coordinate
y: number; // Bottom y coordinate
width: number; // Width
height: number; // Height
}Color
Colors can be created with helper functions:
import { rgb, cmyk, grayscale } from "@libpdf/core";
const red = rgb(1, 0, 0);
const cyan = cmyk(1, 0, 0, 0);
const gray = grayscale(0.5);Rotation
interface Rotation {
angle: number; // Degrees
origin?: { x: number; y: number }; // Rotation center
}LineCap
type LineCap = "butt" | "round" | "square";LineJoin
type LineJoin = "miter" | "round" | "bevel";