pdfcpu
| Language | Go |
|---|---|
| License | Apache-2.0 |
| Repository | github.com/pdfcpu/pdfcpu |
| Documentation | pdfcpu.io, API on pkg.go.dev |
| Depends on | nothing outside Go (pure Go, no cgo) |
| Read / write | yes / yes: validate, optimize, merge, split, rotate, trim, encrypt, watermark, stamp, forms, attachments, images, fonts; no text extraction or rendering |
pdfcpu processes existing PDF files in pure Go. The api package has one function per operation, usually in two forms: XxxFile(ctx, inFile, outFile, ...) working on paths and Xxx(ctx, rs io.ReadSeeker, w io.Writer, ...) working on streams. The same operations are available as the pdfcpu command-line tool. It validates files against the spec, optimizes them (removes duplicate objects, writes object streams), handles AES-256 encryption, adds text, image and PDF watermarks and stamps, and fills, locks and exports AcroForms through JSON.
pdfcpu doesn’t extract text or render pages; use ledongthuc/pdf or go-fitz for that. Its JSON-based create command builds simple documents, but it isn’t a layout library.
In current versions every api function takes a context.Context as the first argument. Pages are numbered from 1; page selections are strings like "1-3", "5", "even", "!2" (all except page 2). Passing nil as the configuration uses the defaults.
Installation#
go get github.com/pdfcpu/pdfcpu@latest
# command-line tool
go install github.com/pdfcpu/pdfcpu/cmd/pdfcpu@latest
Basic usage: merge PDF files#
package main
import (
"context"
"log"
"github.com/pdfcpu/pdfcpu/pkg/api"
)
func main() {
ctx := context.Background()
inFiles := []string{"a.pdf", "b.pdf", "c.pdf"}
// false: no blank divider page between merged files
if err := api.MergeCreateFile(ctx, inFiles, "merged.pdf", false, nil); err != nil {
log.Fatal(err)
}
n, err := api.PageCountFile(ctx, "merged.pdf")
if err != nil {
log.Fatal(err)
}
log.Printf("merged.pdf has %d pages", n)
}
Command line: pdfcpu merge merged.pdf a.pdf b.pdf c.pdf.
How to split a PDF#
// one file per page, written to the existing directory "out"
err := api.SplitFile(ctx, "in.pdf", "out", 1, nil)
// split before pages 3 and 7: pages 1-2, 3-6, 7-end
err = api.SplitByPageNrFile(ctx, "in.pdf", "out", []int{3, 7}, nil)
// copy selected pages into a new file
err = api.CollectFile(ctx, "in.pdf", "selection.pdf", []string{"1-3", "5"}, nil)
How to rotate pages#
// rotate pages 1-3 by 90 degrees clockwise; nil selects all pages
err := api.RotateFile(ctx, "in.pdf", "rotated.pdf", 90, []string{"1-3"}, nil)
How to encrypt and decrypt a PDF#
import "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/model"
conf := model.NewAESConfiguration("user", "owner", 256)
if err := api.EncryptFile(ctx, "in.pdf", "encrypted.pdf", conf); err != nil {
log.Fatal(err)
}
dconf := model.NewDefaultConfiguration()
dconf.OwnerPW = "owner"
if err := api.DecryptFile(ctx, "encrypted.pdf", "decrypted.pdf", dconf); err != nil {
log.Fatal(err)
}
How to read PDF metadata#
import "os"
f, err := os.Open("in.pdf")
if err != nil {
log.Fatal(err)
}
defer f.Close()
info, err := api.PDFInfo(ctx, f, "in.pdf", nil, false, nil)
if err != nil {
log.Fatal(err)
}
log.Printf("PDF %s, %d pages, title %q, author %q, producer %q, encrypted %v, tagged %v",
info.Version, info.PageCount, info.Title, info.Author, info.Producer, info.Encrypted, info.Tagged)
Command line: pdfcpu info in.pdf.
How to add a text watermark#
// description string: font, size, position, opacity, rotation, ...
err := api.AddTextWatermarksFile(ctx, "in.pdf", "watermarked.pdf", nil, true,
"CONFIDENTIAL", "font:Helvetica, points:48, rot:45, op:0.3, fillc:.8 0 0", nil)
onTop true makes a stamp (over the content); false makes a watermark (behind it).
How to fill a PDF form#
Export the form to JSON, edit the values, and fill:
// writes the fields and their current values
err := api.ExportFormFile(ctx, "form.pdf", "form.json", nil)
// ... edit "value" entries in form.json ...
err = api.FillFormFile(ctx, "form.pdf", "form.json", "filled.pdf", nil)
api.ListFormFields lists field names; api.LockFormFieldsFile makes fields read-only.
Tips#
pdfcpu validate -mode strict in.pdfreports spec violations;pdfcpu optimize in.pdf out.pdfmakes files smaller.api.ExtractImagesFileandapi.ExtractFontsFilesave embedded images and fonts;api.ExtractContentFiledumps raw content streams.- pdfcpu keeps a configuration file in the user config directory; call
api.DisableConfigDir()in servers and tests to use built-in defaults.