All formats

ledongthuc/pdf

LanguageGo
LicenseBSD-3-Clause
Repositorygithub.com/ledongthuc/pdf
Documentationpkg.go.dev/github.com/ledongthuc/pdf
Depends onnothing (pure Go)
Read / writeyes (text, page objects) / no

ledongthuc/pdf is a fork of Russ Cox’s rsc.io/pdf reader with text-extraction helpers. It parses the PDF object structure, decodes Flate streams and maps font encodings (including ToUnicode CMaps) to text. It’s small, has no dependencies and no cgo, which makes it handy for indexing and simple extraction in Go services.

It’s a reader only, and limited: no rendering, no layout analysis beyond grouping by rows, weak support for some encrypted files and unusual fonts. The repository has no tagged releases, so go get records a pseudo-version. For accurate text from complex documents, use go-fitz (MuPDF) or an external tool like pdftotext.

Installation#

Shell
go get github.com/ledongthuc/pdf

Basic usage: extract plain text#

Go
package main

import (
	"bytes"
	"fmt"
	"log"

	"github.com/ledongthuc/pdf"
)

func main() {
	f, r, err := pdf.Open("in.pdf")
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	fmt.Printf("%d pages\n", r.NumPage())

	plain, err := r.GetPlainText()  // io.Reader with the text of all pages
	if err != nil {
		log.Fatal(err)
	}
	var buf bytes.Buffer
	if _, err := buf.ReadFrom(plain); err != nil {
		log.Fatal(err)
	}
	fmt.Println(buf.String())
}

How to get text with fonts and positions#

GetStyledTexts returns text runs with their font name, size and coordinates:

Go
texts, err := r.GetStyledTexts()
if err != nil {
	log.Fatal(err)
}
for _, t := range texts {
	fmt.Printf("%q font=%s size=%.1f x=%.1f y=%.1f\n", t.S, t.Font, t.FontSize, t.X, t.Y)
}

How to extract text page by page, grouped by rows#

Go
for i := 1; i <= r.NumPage(); i++ {
	p := r.Page(i)
	if p.V.IsNull() {
		continue
	}
	rows, err := p.GetTextByRow()
	if err != nil {
		log.Printf("page %d: %v", i, err)
		continue
	}
	for _, row := range rows {
		var line string
		for _, word := range row.Content {
			line += word.S
		}
		fmt.Printf("page %d, row %d: %s\n", i, row.Position, line)
	}
}

p.GetPlainText(fonts) returns the text of a single page; pass nil to let it load the page’s fonts.

How to read the document information dictionary#

The Trailer() method gives access to raw PDF objects:

Go
info := r.Trailer().Key("Info")
for _, key := range []string{"Title", "Author", "Producer"} {
	if v := info.Key(key); !v.IsNull() {
		fmt.Printf("%s: %s\n", key, v.Text())
	}
}

Tips#