SkillAgentSearch skills...

ExtractPDF4J

Java PDF table extraction & OCR library. Extract structured tables from text-based and scanned PDFs using stream, lattice (OpenCV-style grid detection), and hybrid parsing.

Install / Use

npx skills add ExtractPDF4J/ExtractPDF4J

Installs into whichever agent you are using.

README

GitHub stars


<br /> <p align="center"> <a href="https://extractpdf4j.github.io/ExtractPDF4J/"> <picture> <source media="(prefers-color-scheme: dark)" srcset="./docs/images/extractpdf4j-banner-dark.png"> <img alt="ExtractPDF4J - Java-native PDF table extraction for real-world documents" width="900" src="./docs/images/extractpdf4j-banner-light.png" /> </picture> </a> </p> <p align="center"> <a href="https://extractpdf4j.github.io/ExtractPDF4J/" target="_blank">→ extractpdf4j.github.io/ExtractPDF4J ←</a> </p> <p align="center"> Java-native PDF table extraction for text-based, scanned, and image-heavy documents. <br /> <br /> <a href="https://search.maven.org/search?q=io.github.extractpdf4j"> <img src="https://img.shields.io/badge/Maven%20Central-io.github.extractpdf4j-1565C0?style=for-the-badge" alt="Maven Central" /> </a> <a href="https://github.com/ExtractPDF4J/ExtractPDF4J"> <img src="https://img.shields.io/badge/Java-17%2B-1976D2?style=for-the-badge&logo=openjdk&logoColor=white" alt="Java 17+" /> </a> <a href="https://github.com/ExtractPDF4J/ExtractPDF4J/releases/tag/v2.1.0"> <img src="https://img.shields.io/badge/release-v2.1.0-616161?style=for-the-badge" alt="Release v2.1.0" /> </a> <a href="https://github.com/ExtractPDF4J/ExtractPDF4J"> <img src="https://img.shields.io/badge/OCR-supported-5E35B1?style=for-the-badge" alt="OCR Supported" /> </a> <a href="https://extractpdf4j.github.io/ExtractPDF4J/"> <img src="https://img.shields.io/badge/Docs-live-1E88E5?style=for-the-badge" alt="Docs" /> </a> </p> <p align="center"> <a href="https://github.com/ExtractPDF4J/ExtractPDF4J/stargazers"> <img src="https://img.shields.io/github/stars/ExtractPDF4J/ExtractPDF4J?style=for-the-badge" alt="GitHub Stars" /> </a> <a href="https://github.com/ExtractPDF4J/ExtractPDF4J/network/members"> <img src="https://img.shields.io/github/forks/ExtractPDF4J/ExtractPDF4J?style=for-the-badge" alt="GitHub Forks" /> </a> <a href="https://github.com/ExtractPDF4J/ExtractPDF4J/actions"> <img src="https://img.shields.io/github/actions/workflow/status/ExtractPDF4J/ExtractPDF4J/ci.yml?style=for-the-badge&label=build" alt="Build Status" /> </a> <a href="https://github.com/ExtractPDF4J/ExtractPDF4J"> <img src="https://img.shields.io/badge/Downloads-4K%2B-3949AB?style=for-the-badge" alt="Downloads" /> </a> </p> <br /> <p align="center"> <img src="./docs/images/extractpdf4j-demo.gif" alt="ExtractPDF4J demo" width="100%" /> </p>

ExtractPDF4J

A production-focused Java library for extracting tables and structured data from PDFs. Extract tables from scanned/image PDFs in Java using OCR + table structure detection.

import com.extractpdf4j.helpers.Table;
import com.extractpdf4j.parsers.HybridParser;
import java.util.List;

public class QuickStart {
  public static void main(String[] args) throws Exception {
    // Works for BOTH text-based and scanned PDFs (OCR fallback)
    List<Table> tables = new HybridParser("scanned_invoice.pdf")
        .dpi(300f)
        .parse();

    if (!tables.isEmpty()) {
      System.out.println(tables.get(0).toCSV(','));
    }
  }
}

What problem it solves

Stop hand-retyping tables from scanned invoices, bank statements, or reports. Extract clean rows + columns even when the PDF has no text layer.

Supported Document Types

ExtractPDF4J works well with documents such as:

  • bank statements
  • financial reports
  • invoices
  • operational documents
  • structured business reports

Production Use Cases

ExtractPDF4J is designed for production environments such as:

  • fintech and banking platforms
  • document processing pipelines
  • analytics platforms
  • enterprise ingestion workflows
  • AI / ML data preparation pipelines

Magic snippet

The copy/paste quick start is at the top of this README under the project description.


Install (Maven + Gradle)

Maven

Recommended: Using the BOM

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>io.github.extractpdf4j</groupId>
      <artifactId>extractpdf4j-bom</artifactId>
      <version>2.1.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>io.github.extractpdf4j</groupId>
    <artifactId>extractpdf4j-service</artifactId>
  </dependency>
</dependencies>

Direct Module Usage

If you prefer not to use the BOM:

<dependency>
  <groupId>io.github.extractpdf4j</groupId>
  <artifactId>extractpdf4j-core</artifactId>
  <version>2.1.0</version>
</dependency>
<dependency>
  <groupId>io.github.extractpdf4j</groupId>
  <artifactId>extractpdf4j-cli</artifactId>
  <version>2.1.0</version>
</dependency>
<dependency>
  <groupId>io.github.extractpdf4j</groupId>
  <artifactId>extractpdf4j-service</artifactId>
  <version>2.1.0</version>
</dependency>

Gradle

implementation("io.github.extractpdf4j:extractpdf4j-core:2.1.0")
implementation("io.github.extractpdf4j:extractpdf4j-cli:2.1.0")
implementation("io.github.extractpdf4j:extractpdf4j-service:2.1.0")

Documentation

Project documentation lives in /docs and is published to GitHub Pages. For contributor-focused MkDocs workflow details, see docs/docs-development.md.

Build docs locally

pip install -r docs/requirements.txt
mkdocs build --strict

Serve docs locally

mkdocs serve

Docs dependencies are pinned to MkDocs 1.x in docs/requirements.txt because MkDocs 2.0 currently warns as incompatible with Material for MkDocs.


Why this vs Tabula/PDFBox (comparison table)

| Feature | ExtractPDF4J | Tabula-Java | PDFBox | | ------------------ | --------------------------- | ----------- | ------------ | | Text-based PDFs | ✅ | ✅ | ✅ | | Scanned/Image PDFs | ✅ Native OCR | ❌ | ❌ | | Table recognition | ✅ Stream/Lattice/OCR-hybrid | ✅ | ❌ (raw text) | | “Hello world” time | Low (single entrypoint) | Medium | High |

Use cases (3 quick examples)

Extract from scanned PDF (OCR)

import com.extractpdf4j.helpers.Table;
import com.extractpdf4j.parsers.OcrStreamParser;
import java.util.List;

List<Table> tables = new OcrStreamParser("scanned_invoice.pdf")
  .dpi(300f)
  .parse();

Extract from text-based PDF (stream/lattice)

import com.extractpdf4j.helpers.Table;
import com.extractpdf4j.parsers.StreamParser;
import java.util.List;

List<Table> tables = new StreamParser("statement.pdf")
  .pages("1-2")
  .parse();

Batch extraction (folder → CSV)

import com.extractpdf4j.helpers.Table;
import com.extractpdf4j.parsers.HybridParser;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

for (File pdf : new File("./invoices").listFiles(f -> f.getName().endsWith(".pdf"))) {
  List<Table> tables = new HybridParser(pdf.getPath())
    .dpi(300f)
    .parse();
  if (!tables.isEmpty()) {
    Files.writeString(Path.of("./out/" + pdf.getName() + ".csv"), tables.get(0).toCSV(','));
  }
}

Custom CSV Delimiter

import com.extractpdf4j.helpers.CsvExporter;

CsvExporter exporter = new CsvExporter();
exporter.setDelimiter(";");
exporter.export(data);

Annotation-based configuration

If you prefer declarative configuration, you can annotate a class and build the parser from that annotation.

import com.extractpdf4j.annotations.ExtractPdfAnnotations;
import com.extractpdf4j.annotations.ExtractPdfConfig;
import com.extractpdf4j.annotations.ParserMode;
import com.extractpdf4j.parsers.BaseParser;

@ExtractPdfConfig(
  parser = ParserMode.HYBRID,
  pages = "all",
  dpi = 300f,
  debug = true
)
class InvoiceParserConfig {}

BaseParser parser = ExtractPdfAnnotations.parserFrom(InvoiceParserConfig.class, "invoice.pdf");

Tesseract/OpenCV setup (only what’s necessary)

  • Recommended: use the Bytedeco *-platform artifacts so native binaries are bundled.
  • If you bring your own OCR/OpenCV install, ensure native libraries are on the OS path (LD_LIBRARY_PATH/DYLD_LIBRARY_PATH/PATH).
  • For OCR, set TESSDATA_PREFIX if Tesseract language data is not found.

API reference (Javadocs link)


Sample PDFs

The /examples directory contains publicly available, non-sensitive PDF files that can be used to test and understand different extraction scenarios supported by ExtractPDF4J.

  • sample_utility_bill.pdf
    A sample utility bill demonstrating structured text extraction, including dates, addresses, account identifiers, and billing totals.

  • sample_monthly_statement.pdf
    A multi-page sample financial statement demonstrating table extraction from repeated layouts and tabular data. All content is explicitly marked as sample data.


Visual examples

extractpdf4j-table.png

extractpdf4j-visual.png


Developer documentation

This section keeps the full project details (architecture, CLI, configuration, and setup) for contributors.

Architecture

PDF (text-based) ──► PDFBox text positions ─┐
                                            ├─► StreamParser ──► Table (cells)
PDF (scanned)    ──► Render to image ──► OpenCV lines/grids ──► LatticeParser ──► Table
                                

Related Skills

View on GitHub
GitHub Stars536
CategoryDevelopment
Updated7h ago
Forks36

Languages

Java

Security Score

85/100

Audited on Aug 8, 2026

No findings