Skip to content
Extracting text and data from PDF files

Extracting text and data from PDF files

The extractor package handles all of it. Build an extractor for a page, then ask it for text, tables, images or fonts.

page, err := pdfReader.GetPage(pageNum)
if err != nil {
    return err
}

ex, err := extractor.New(page)
if err != nil {
    return err
}

text, err := ex.ExtractText()
if err != nil {
    return err
}
fmt.Println(text)

Extraction is per page, so a whole document is a loop over GetPage.

What the extractor returns

CallReturns
ExtractText()The page text as one string.
ExtractTextWithStats()The same string, plus the character count and the number of characters that could not be decoded.
ExtractPageText()A *PageText and the same two counts. This is the structured form: text, marks, tables.
ExtractPageImages(opts)Every image drawn on the page with its position, displayed size and rotation.
ExtractFonts(prev)The fonts used, including embedded font files. Pass the previous page’s result to build a deduplicated list across a document.
ExtractStrokePaths()The stroked path geometry, in any extraction mode.

Characters that cannot be decoded come back as U+FFFD rather than being dropped, so a run of replacement characters in the output points at a font with a broken or missing ToUnicode map, not at a bug in the extraction. ExtractTextWithStats gives you the miss count without inspecting the string.

PageText is where the structure lives:

  • Text() is the same string ExtractText returns.
  • Marks() gives every TextMark, usually one per glyph, each with its bounding box, font, size, fill and stroke color. TextMarkArray.RangeOffset maps a substring of the extracted text back to the marks that produced it, and BBox() turns those into a rectangle, which is how you locate a phrase on the page.
  • Tables() returns the detected tables as rows and cells.
  • GridText() returns the fixed-width grid layout regardless of the mode in effect.
  • ApplyArea(bbox) narrows everything above to a region of the page and can be called repeatedly with different rectangles.

Choosing an extraction mode

extractor.NewWithOptions takes an Options value, and ExtractionMode is the field that changes the output most.

ModeWhat it does
ExtractionModeLayout (default)Infers paragraphs, reading order and tables. Marks() and Tables() are populated.
ExtractionModePlainReads the content streams in order. Fastest, most complete text, no marks or tables.
ExtractionModeLayoutNoBreaksLayout, without line breaks inside a single horizontal line.
ExtractionModeGridWords placed on a fixed-width character grid. Marks() and Tables() come back empty.

Layout mode is what you want when you need positions or are feeding search and replace, which depends on marks. Plain mode is worth trying whenever text is duplicated or missing. The other Options fields cover annotation text (IncludeAnnotations), clipping to the crop box (ApplyCropBox), damaged files (RelaxedMode) and words split across lines (DisableDehyphenation).

Tables and positions

Extracting tables is a separate detection pass over text positions, spacing and rulings, reached through PageText.Tables(). The table extraction guide covers writing the result out as CSV, and it handles several tables on one page, unlike the simpler grid-splitting approach in pdf_to_csv.go.

For working with position and formatting information directly, start from pdf_text_locations.go.

Longer treatments of each: text extraction, image extraction and font extraction.

Last updated on