pdf-lib Drawing Operations
Draw shapes, lines, and SVG paths on PDF pages with full control over colors, borders, opacity, and rotation.
Critical Rules
- Color values are 0.0-1.0, NOT 0-255.
rgb(1, 0, 0) is red. rgb(255, 0, 0) silently produces wrong output.
- drawEllipse uses
xScale/yScale, NOT width/height. These define radii, not diameters.
- drawLine uses
thickness, NOT borderWidth. It also uses dashArray/dashPhase (not borderDashArray/borderDashPhase).
- drawLine uses
start/end point objects, NOT x/y.
- drawCircle and drawSquare use
size, NOT width/height or radius.
- Coordinate origin is bottom-left. Y increases upward. To draw near the top, use
y: height - offset.
- All draw methods are synchronous. No
await needed on page.drawRectangle(), etc.
- ALWAYS import color constructors explicitly:
import { rgb, cmyk, grayscale } from 'pdf-lib'
Required Imports
import {
PDFDocument,
rgb, // rgb(r, g, b) — all 0.0-1.0
cmyk, // cmyk(c, m, y, k) — all 0.0-1.0
grayscale, // grayscale(g) — 0.0 black, 1.0 white
degrees, // degrees(45) → Rotation
radians, // radians(Math.PI / 4) → Rotation
BlendMode, // BlendMode.Normal, .Multiply, etc.
LineCapStyle, // LineCapStyle.Butt, .Round, .Square
} from 'pdf-lib'
Shape Decision Tree
What shape do you need?
├── Filled/stroked box?
│ ├── Square (equal sides) → page.drawSquare({ size })
│ └── Rectangle → page.drawRectangle({ width, height })
├── Rounded/circular?
│ ├── Circle → page.drawCircle({ size }) // size = diameter
│ └── Ellipse → page.drawEllipse({ xScale, yScale }) // radii
├── Line between two points?
│ └── page.drawLine({ start: {x,y}, end: {x,y}, thickness })
└── Complex/custom shape?
└── page.drawSvgPath('M 0,0 L 100,100 ...', { scale, color })
Quick Reference: Color Constructors
| Constructor |
Parameters |
Range |
Example |
rgb(r, g, b) |
Red, Green, Blue |
0.0-1.0 each |
rgb(0, 0.53, 0.71) — teal |
cmyk(c, m, y, k) |
Cyan, Magenta, Yellow, Key |
0.0-1.0 each |
cmyk(1, 0, 0, 0) — cyan |
grayscale(g) |
Gray level |
0.0 (black) to 1.0 (white) |
grayscale(0.5) — mid-gray |
Color type: Color = Grayscale | RGB | CMYK
Common Colors
const black = rgb(0, 0, 0)
const white = rgb(1, 1, 1)
const red = rgb(1, 0, 0)
const green = rgb(0, 1, 0)
const blue = rgb(0, 0, 1)
const yellow = rgb(1, 1, 0)
const gray50 = grayscale(0.5)
Quick Reference: All Shape Methods
drawRectangle
page.drawRectangle({
x: 50, y: 50,
width: 200, height: 100,
color: rgb(0.2, 0.4, 0.8), // fill color
borderColor: rgb(0, 0, 0), // stroke color
borderWidth: 2, // stroke thickness
opacity: 0.9, // fill opacity 0.0-1.0
borderOpacity: 1, // stroke opacity 0.0-1.0
rotate: degrees(15), // rotation
borderDashArray: [6, 3], // dashed border: 6pt dash, 3pt gap
borderDashPhase: 0, // dash offset
borderLineCap: LineCapStyle.Round, // cap style
blendMode: BlendMode.Normal, // blending
})
drawSquare
page.drawSquare({
x: 50, y: 50,
size: 100, // side length (NOT width/height)
color: rgb(1, 0.8, 0),
borderColor: rgb(0, 0, 0),
borderWidth: 1.5,
rotate: degrees(45),
opacity: 1,
borderOpacity: 1,
borderDashArray: [4, 2],
borderDashPhase: 0,
borderLineCap: LineCapStyle.Butt,
blendMode: BlendMode.Normal,
})
drawCircle
page.drawCircle({
x: 200, y: 300, // center point
size: 80, // diameter (NOT radius)
color: rgb(0.9, 0.1, 0.1),
borderColor: rgb(0, 0, 0),
borderWidth: 2,
opacity: 0.7,
borderOpacity: 1,
borderDashArray: [5, 5],
borderDashPhase: 0,
borderLineCap: LineCapStyle.Round,
blendMode: BlendMode.Normal,
})
drawEllipse
page.drawEllipse({
x: 250, y: 400, // center point
xScale: 120, // horizontal RADIUS (NOT width)
yScale: 60, // vertical RADIUS (NOT height)
color: rgb(0.3, 0.7, 0.3),
borderColor: rgb(0, 0, 0),
borderWidth: 1,
rotate: degrees(30),
opacity: 0.8,
borderOpacity: 1,
blendMode: BlendMode.Normal,
})
drawLine
CRITICAL: drawLine uses DIFFERENT option names than other shapes.
page.drawLine({
start: { x: 50, y: 500 }, // start point object
end: { x: 400, y: 500 }, // end point object
thickness: 2, // NOT borderWidth
color: rgb(0, 0, 0), // line color (NOT borderColor)
opacity: 1,
dashArray: [10, 5], // NOT borderDashArray
dashPhase: 0, // NOT borderDashPhase
lineCap: LineCapStyle.Butt, // NOT borderLineCap
blendMode: BlendMode.Normal,
})
drawSvgPath
page.drawSvgPath(
'M 0,20 L 100,160 Q 130,200 150,120 C 190,-40 200,200 300,150 L 400,90',
{
x: 50, y: 700, // offset position
color: rgb(0.8, 0.2, 0.2), // fill color
borderColor: rgb(0, 0, 0), // stroke color
borderWidth: 2, // stroke width
opacity: 1,
borderOpacity: 1,
scale: 0.5, // scale factor
rotate: degrees(0),
blendMode: BlendMode.Normal,
}
)
Drawing Options Cross-Reference Table
| Option |
Rectangle |
Square |
Circle |
Ellipse |
Line |
SVG Path |
x, y |
YES |
YES |
YES (center) |
YES (center) |
NO |
YES (offset) |
width, height |
YES |
NO |
NO |
NO |
NO |
NO |
size |
NO |
YES |
YES (diameter) |
NO |
NO |
NO |
xScale, yScale |
NO |
NO |
NO |
YES (radii) |
NO |
NO |
start, end |
NO |
NO |
NO |
NO |
YES |
NO |
color |
YES |
YES |
YES |
YES |
YES |
YES |
opacity |
YES |
YES |
YES |
YES |
YES |
YES |
borderColor |
YES |
YES |
YES |
YES |
NO |
YES |
borderWidth |
YES |
YES |
YES |
YES |
NO |
YES |
borderOpacity |
YES |
YES |
YES |
YES |
NO |
YES |
thickness |
NO |
NO |
NO |
NO |
YES |
NO |
rotate |
YES |
YES |
NO |
YES |
NO |
YES |
scale |
NO |
NO |
NO |
NO |
NO |
YES |
borderDashArray |
YES |
YES |
YES |
NO |
NO |
NO |
borderDashPhase |
YES |
YES |
YES |
NO |
NO |
NO |
borderLineCap |
YES |
YES |
YES |
NO |
NO |
NO |
dashArray |
NO |
NO |
NO |
NO |
YES |
NO |
dashPhase |
NO |
NO |
NO |
NO |
YES |
NO |
lineCap |
NO |
NO |
NO |
NO |
YES |
NO |
blendMode |
YES |
YES |
YES |
YES |
YES |
YES |
Enums Reference
BlendMode
BlendMode.Normal | Multiply | Screen | Overlay | Darken | Lighten | ColorDodge | ColorBurn | HardLight | SoftLight | Difference | Exclusion
LineCapStyle
| Value |
Description |
LineCapStyle.Butt |
Flat edge at endpoint (default) |
LineCapStyle.Round |
Rounded cap extending past endpoint |
LineCapStyle.Square |
Square cap extending past endpoint |
LineJoinStyle
| Value |
Description |
LineJoinStyle.Miter |
Sharp corner (default) |
LineJoinStyle.Round |
Rounded corner |
LineJoinStyle.Bevel |
Flattened corner |
Rotation
import { degrees, radians } from 'pdf-lib'
// Use degrees() or radians() to create Rotation values
page.drawRectangle({ x: 100, y: 100, width: 80, height: 40, rotate: degrees(45) })
page.drawRectangle({ x: 300, y: 100, width: 80, height: 40, rotate: radians(Math.PI / 6) })
SVG Path Commands Reference
| Command |
Parameters |
Description |
M x,y |
Move to |
Start a new sub-path |
L x,y |
Line to |
Draw straight line |
H x |
Horizontal line |
Draw horizontal line |
V y |
Vertical line |
Draw vertical line |
C x1,y1 x2,y2 x,y |
Cubic bezier |
Curve with two control points |
Q x1,y1 x,y |
Quadratic bezier |
Curve with one control point |
A rx,ry rot large-arc sweep x,y |
Arc |
Elliptical arc |
Z |
Close path |
Close current sub-path |
Lowercase variants (m, l, h, v, c, q, a, z) use relative coordinates.
Reference Links
- Complete method signatures
- Code examples
- Anti-patterns and common mistakes
1---2name: pdflib-syntax-drawing3description: Use when drawing shapes, lines, or SVG paths on PDF pages with pdf-lib. Prevents the common color value mistake: pdf-lib uses 0-1 range for rgb/cmyk, not 0-255. Covers drawRectangle, drawCircle, drawLine, drawSvgPath, color constructors (rgb, cmyk, grayscale), rotation helpers. Keywords: drawRectangle, drawCircle, drawLine, drawSvgPath, rgb, cmyk, grayscale, BlendMode, draw shapes, add line, draw on PDF, colors, rectangles circles, SVG path.4license: MIT5---67# pdf-lib Drawing Operations89> Draw shapes, lines, and SVG paths on PDF pages with full control over colors, borders, opacity, and rotation.1011## Critical Rules1213- **Color values are 0.0-1.0, NOT 0-255.** `rgb(1, 0, 0)` is red. `rgb(255, 0, 0)` silently produces wrong output.14- **drawEllipse uses `xScale`/`yScale`, NOT `width`/`height`.** These define radii, not diameters.15- **drawLine uses `thickness`, NOT `borderWidth`.** It also uses `dashArray`/`dashPhase` (not `borderDashArray`/`borderDashPhase`).16- **drawLine uses `start`/`end` point objects, NOT `x`/`y`.**17- **drawCircle and drawSquare use `size`, NOT `width`/`height` or `radius`.**18- **Coordinate origin is bottom-left.** Y increases upward. To draw near the top, use `y: height - offset`.19- **All draw methods are synchronous.** No `await` needed on `page.drawRectangle()`, etc.20- **ALWAYS import color constructors explicitly:** `import { rgb, cmyk, grayscale } from 'pdf-lib'`2122## Required Imports2324```typescript25import {26 PDFDocument,27 rgb, // rgb(r, g, b) — all 0.0-1.028 cmyk, // cmyk(c, m, y, k) — all 0.0-1.029 grayscale, // grayscale(g) — 0.0 black, 1.0 white30 degrees, // degrees(45) → Rotation31 radians, // radians(Math.PI / 4) → Rotation32 BlendMode, // BlendMode.Normal, .Multiply, etc.33 LineCapStyle, // LineCapStyle.Butt, .Round, .Square34} from 'pdf-lib'35```3637## Shape Decision Tree3839```40What shape do you need?41├── Filled/stroked box?42│ ├── Square (equal sides) → page.drawSquare({ size })43│ └── Rectangle → page.drawRectangle({ width, height })44├── Rounded/circular?45│ ├── Circle → page.drawCircle({ size }) // size = diameter46│ └── Ellipse → page.drawEllipse({ xScale, yScale }) // radii47├── Line between two points?48│ └── page.drawLine({ start: {x,y}, end: {x,y}, thickness })49└── Complex/custom shape?50 └── page.drawSvgPath('M 0,0 L 100,100 ...', { scale, color })51```5253## Quick Reference: Color Constructors5455| Constructor | Parameters | Range | Example |56|------------|-----------|-------|---------|57| `rgb(r, g, b)` | Red, Green, Blue | 0.0-1.0 each | `rgb(0, 0.53, 0.71)` — teal |58| `cmyk(c, m, y, k)` | Cyan, Magenta, Yellow, Key | 0.0-1.0 each | `cmyk(1, 0, 0, 0)` — cyan |59| `grayscale(g)` | Gray level | 0.0 (black) to 1.0 (white) | `grayscale(0.5)` — mid-gray |6061**Color type:** `Color = Grayscale | RGB | CMYK`6263### Common Colors6465```typescript66const black = rgb(0, 0, 0)67const white = rgb(1, 1, 1)68const red = rgb(1, 0, 0)69const green = rgb(0, 1, 0)70const blue = rgb(0, 0, 1)71const yellow = rgb(1, 1, 0)72const gray50 = grayscale(0.5)73```7475## Quick Reference: All Shape Methods7677### drawRectangle7879```typescript80page.drawRectangle({81 x: 50, y: 50,82 width: 200, height: 100,83 color: rgb(0.2, 0.4, 0.8), // fill color84 borderColor: rgb(0, 0, 0), // stroke color85 borderWidth: 2, // stroke thickness86 opacity: 0.9, // fill opacity 0.0-1.087 borderOpacity: 1, // stroke opacity 0.0-1.088 rotate: degrees(15), // rotation89 borderDashArray: [6, 3], // dashed border: 6pt dash, 3pt gap90 borderDashPhase: 0, // dash offset91 borderLineCap: LineCapStyle.Round, // cap style92 blendMode: BlendMode.Normal, // blending93})94```9596### drawSquare9798```typescript99page.drawSquare({100 x: 50, y: 50,101 size: 100, // side length (NOT width/height)102 color: rgb(1, 0.8, 0),103 borderColor: rgb(0, 0, 0),104 borderWidth: 1.5,105 rotate: degrees(45),106 opacity: 1,107 borderOpacity: 1,108 borderDashArray: [4, 2],109 borderDashPhase: 0,110 borderLineCap: LineCapStyle.Butt,111 blendMode: BlendMode.Normal,112})113```114115### drawCircle116117```typescript118page.drawCircle({119 x: 200, y: 300, // center point120 size: 80, // diameter (NOT radius)121 color: rgb(0.9, 0.1, 0.1),122 borderColor: rgb(0, 0, 0),123 borderWidth: 2,124 opacity: 0.7,125 borderOpacity: 1,126 borderDashArray: [5, 5],127 borderDashPhase: 0,128 borderLineCap: LineCapStyle.Round,129 blendMode: BlendMode.Normal,130})131```132133### drawEllipse134135```typescript136page.drawEllipse({137 x: 250, y: 400, // center point138 xScale: 120, // horizontal RADIUS (NOT width)139 yScale: 60, // vertical RADIUS (NOT height)140 color: rgb(0.3, 0.7, 0.3),141 borderColor: rgb(0, 0, 0),142 borderWidth: 1,143 rotate: degrees(30),144 opacity: 0.8,145 borderOpacity: 1,146 blendMode: BlendMode.Normal,147})148```149150### drawLine151152**CRITICAL:** drawLine uses DIFFERENT option names than other shapes.153154```typescript155page.drawLine({156 start: { x: 50, y: 500 }, // start point object157 end: { x: 400, y: 500 }, // end point object158 thickness: 2, // NOT borderWidth159 color: rgb(0, 0, 0), // line color (NOT borderColor)160 opacity: 1,161 dashArray: [10, 5], // NOT borderDashArray162 dashPhase: 0, // NOT borderDashPhase163 lineCap: LineCapStyle.Butt, // NOT borderLineCap164 blendMode: BlendMode.Normal,165})166```167168### drawSvgPath169170```typescript171page.drawSvgPath(172 'M 0,20 L 100,160 Q 130,200 150,120 C 190,-40 200,200 300,150 L 400,90',173 {174 x: 50, y: 700, // offset position175 color: rgb(0.8, 0.2, 0.2), // fill color176 borderColor: rgb(0, 0, 0), // stroke color177 borderWidth: 2, // stroke width178 opacity: 1,179 borderOpacity: 1,180 scale: 0.5, // scale factor181 rotate: degrees(0),182 blendMode: BlendMode.Normal,183 }184)185```186187## Drawing Options Cross-Reference Table188189| Option | Rectangle | Square | Circle | Ellipse | Line | SVG Path |190|--------|:---------:|:------:|:------:|:-------:|:----:|:--------:|191| `x`, `y` | YES | YES | YES (center) | YES (center) | NO | YES (offset) |192| `width`, `height` | YES | NO | NO | NO | NO | NO |193| `size` | NO | YES | YES (diameter) | NO | NO | NO |194| `xScale`, `yScale` | NO | NO | NO | YES (radii) | NO | NO |195| `start`, `end` | NO | NO | NO | NO | YES | NO |196| `color` | YES | YES | YES | YES | YES | YES |197| `opacity` | YES | YES | YES | YES | YES | YES |198| `borderColor` | YES | YES | YES | YES | NO | YES |199| `borderWidth` | YES | YES | YES | YES | NO | YES |200| `borderOpacity` | YES | YES | YES | YES | NO | YES |201| `thickness` | NO | NO | NO | NO | YES | NO |202| `rotate` | YES | YES | NO | YES | NO | YES |203| `scale` | NO | NO | NO | NO | NO | YES |204| `borderDashArray` | YES | YES | YES | NO | NO | NO |205| `borderDashPhase` | YES | YES | YES | NO | NO | NO |206| `borderLineCap` | YES | YES | YES | NO | NO | NO |207| `dashArray` | NO | NO | NO | NO | YES | NO |208| `dashPhase` | NO | NO | NO | NO | YES | NO |209| `lineCap` | NO | NO | NO | NO | YES | NO |210| `blendMode` | YES | YES | YES | YES | YES | YES |211212## Enums Reference213214### BlendMode215216`BlendMode.Normal` | `Multiply` | `Screen` | `Overlay` | `Darken` | `Lighten` | `ColorDodge` | `ColorBurn` | `HardLight` | `SoftLight` | `Difference` | `Exclusion`217218### LineCapStyle219220| Value | Description |221|-------|------------|222| `LineCapStyle.Butt` | Flat edge at endpoint (default) |223| `LineCapStyle.Round` | Rounded cap extending past endpoint |224| `LineCapStyle.Square` | Square cap extending past endpoint |225226### LineJoinStyle227228| Value | Description |229|-------|------------|230| `LineJoinStyle.Miter` | Sharp corner (default) |231| `LineJoinStyle.Round` | Rounded corner |232| `LineJoinStyle.Bevel` | Flattened corner |233234## Rotation235236```typescript237import { degrees, radians } from 'pdf-lib'238239// Use degrees() or radians() to create Rotation values240page.drawRectangle({ x: 100, y: 100, width: 80, height: 40, rotate: degrees(45) })241page.drawRectangle({ x: 300, y: 100, width: 80, height: 40, rotate: radians(Math.PI / 6) })242```243244## SVG Path Commands Reference245246| Command | Parameters | Description |247|---------|-----------|-------------|248| `M x,y` | Move to | Start a new sub-path |249| `L x,y` | Line to | Draw straight line |250| `H x` | Horizontal line | Draw horizontal line |251| `V y` | Vertical line | Draw vertical line |252| `C x1,y1 x2,y2 x,y` | Cubic bezier | Curve with two control points |253| `Q x1,y1 x,y` | Quadratic bezier | Curve with one control point |254| `A rx,ry rot large-arc sweep x,y` | Arc | Elliptical arc |255| `Z` | Close path | Close current sub-path |256257Lowercase variants (m, l, h, v, c, q, a, z) use relative coordinates.258259## Reference Links260261- [Complete method signatures](references/methods.md)262- [Code examples](references/examples.md)263- [Anti-patterns and common mistakes](references/anti-patterns.md)