All formats

go-fitz

LanguageGo (cgo, or experimental purego without cgo)
LicenseAGPL-3.0 (go-fitz itself and the bundled MuPDF)
Repositorygithub.com/gen2brain/go-fitz
Documentationpkg.go.dev/github.com/gen2brain/go-fitz
Depends onMuPDF (static libraries bundled for common platforms; or an external MuPDF with the extlib build tag)
Read / writeyes (render, text, HTML, SVG, links, outline, metadata) / no

go-fitz gives Go programs MuPDF’s rendering and text extraction: Image renders a page to *image.RGBA, Text returns the page text, HTML and SVG convert a page, and ToC, Links and Metadata read document structure. It opens everything MuPDF opens: PDF, EPUB, MOBI, XPS, CBZ, FB2 and Office documents. Static MuPDF builds are included for Linux, macOS and Windows (amd64, arm64), so go get works with only a C compiler.

go-fitz can’t modify or create PDFs. It is AGPL-3.0: if you distribute your program or run it as a network service, you must release your source under the AGPL (or get a commercial MuPDF license from Artifex and use your own build). Each Document has its own MuPDF context: use one document per goroutine.

Installation#

Shell
go get github.com/gen2brain/go-fitz

Needs cgo (a C compiler). The bundled libraries lack CJK fonts; for CJK documents build against a system MuPDF with go build -tags extlib. With CGO_ENABLED=0 (or -tags nocgo) go-fitz loads a libmupdf shared library at runtime via purego.

Basic usage: render pages to PNG#

Go
package main

import (
	"fmt"
	"image/png"
	"log"
	"os"

	"github.com/gen2brain/go-fitz"
)

func main() {
	doc, err := fitz.New("in.pdf")
	if err != nil {
		log.Fatal(err)
	}
	defer doc.Close()

	fmt.Printf("%d pages\n", doc.NumPage())
	for n := 0; n < doc.NumPage(); n++ {  // pages are numbered from 0
		img, err := doc.ImageDPI(n, 150)
		if err != nil {
			log.Fatal(err)
		}
		f, err := os.Create(fmt.Sprintf("page-%03d.png", n+1))
		if err != nil {
			log.Fatal(err)
		}
		if err := png.Encode(f, img); err != nil {
			log.Fatal(err)
		}
		f.Close()
	}
}

doc.Image(n) renders at the default 300 DPI; doc.ImagePNG(n, dpi) returns encoded PNG bytes directly.

How to extract text from a PDF#

Go
for n := 0; n < doc.NumPage(); n++ {
	text, err := doc.Text(n)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("--- page %d ---\n%s\n", n+1, text)
}

doc.HTML(n, true) returns the page as HTML with positioned text and fonts.

How to read PDF metadata and the table of contents#

Go
meta := doc.Metadata()  // keys like "title", "author", "format", "producer"
fmt.Println(meta["title"], meta["author"], meta["format"])

toc, err := doc.ToC()
if err == nil {
	for _, item := range toc {
		fmt.Printf("%*s%s (page %d)\n", item.Level*2, "", item.Title, item.Page)
	}
}

How to open a PDF from memory#

Go
data, err := os.ReadFile("in.pdf")
if err != nil {
	log.Fatal(err)
}
doc, err := fitz.NewFromMemory(data)

fitz.NewFromReader(r) reads from an io.Reader.

Tips#