Skip to content

Scoped Extraction — Pull Content from a Specific Region

When you’re processing invoices, bank statements, tax forms, or any templated layout, you usually know where the fields live. Instead of extracting the whole page and searching for the value, point PDF Oxide at the exact rectangle and get back just what’s there.

The fluent within(page, rect) API returns a scoped region you can chain extraction methods on: extract_text(), extract_words(), extract_chars(), extract_tables().

Binding coverage. within(page, rect) is available in Python, Rust, and WASM. Go and C# expose the equivalent lower-level helpers (ExtractTextInRect, ExtractWordsInRect, ExtractImagesInRect) — see below.

Quick Example

rect is (x, y, width, height) in PDF points, with the origin at the bottom-left of the page. Letter-size pages are 612 × 792 points.

Python

from pdf_oxide import PdfDocument

doc = PdfDocument("invoice.pdf")

# Top 92 points of page 0 — typical header band
header = doc.within(0, (0, 700, 612, 92)).extract_text()
print(header)

Rust

use pdf_oxide::PdfDocument;
use pdf_oxide::geometry::Rect;

let mut doc = PdfDocument::open("invoice.pdf")?;
let header = doc.within(0, Rect::new(0.0, 700.0, 612.0, 92.0)).extract_text()?;
println!("{}", header);

JavaScript (WASM)

import { WasmPdfDocument } from "pdf-oxide-wasm";

const doc = new WasmPdfDocument(bytes);
const headerRegion = doc.within(0, [0, 700, 612, 92]);
console.log(headerRegion.extractText());
doc.free();

Go (lower-level helper, same effect)

package main

import (
    "fmt"
    "log"
    pdfoxide "github.com/yfedoseev/pdf_oxide/go"
)

func main() {
    doc, err := pdfoxide.Open("invoice.pdf")
    if err != nil { log.Fatal(err) }
    defer doc.Close()

    // ExtractTextInRect(pageIndex, x, y, width, height)
    header, _ := doc.ExtractTextInRect(0, 0, 700, 612, 92)
    fmt.Println(header)
}

C# (lower-level helper)

using PdfOxide;

using var doc = PdfDocument.Open("invoice.pdf");
string header = doc.ExtractTextInRect(0, 0, 700, 612, 92);
Console.WriteLine(header);

Chained extraction from a region

The within() fluent form in Python / Rust / WASM lets you call any extraction method on the same scoped region without re-specifying the rect:

Python

doc = PdfDocument("invoice.pdf")
region = doc.within(0, (400, 100, 200, 200))   # bottom-right 200×200 box

total_text = region.extract_text()              # plain text
words      = region.extract_words()             # word-level records
chars      = region.extract_chars()             # character-level records

Rust

let region = doc.within(0, Rect::new(400.0, 100.0, 200.0, 200.0));
let text  = region.extract_text()?;
let words = region.extract_words()?;

Common use cases

Invoice field extraction

An invoice usually has the vendor address, invoice number, and line-item table in fixed zones. Define the rects once per template:

from pdf_oxide import PdfDocument

TEMPLATES = {
    "acme_v1": {
        "invoice_no":  (450, 720,  120,  20),
        "issue_date":  (450, 700,  120,  20),
        "vendor_name": ( 50, 740,  300,  40),
        "total":       (450, 100,  120,  24),
    },
}

def parse_invoice(path, template):
    doc = PdfDocument(path)
    out = {}
    for field, rect in template.items():
        out[field] = doc.within(0, rect).extract_text().strip()
    return out

print(parse_invoice("invoice-2025-04.pdf", TEMPLATES["acme_v1"]))

Bank statement line items

Most statements have a narrow “transactions” band. Crop to that band and call extract_words() to get each line in reading order with its bbox:

doc = PdfDocument("statement.pdf")
for page in range(doc.page_count()):
    txn_region = doc.within(page, (36, 72, 540, 650))   # skip header + footer
    for w in txn_region.extract_words():
        print(f"page {page}: {w.text} at ({w.x0:.0f},{w.y0:.0f})")

If you’re indexing the body content only, crop away the top and bottom of every page:

Rust

let mut doc = PdfDocument::open("book.pdf")?;
for i in 0..doc.page_count()? {
    let body = doc.within(i, Rect::new(0.0, 100.0, 612.0, 600.0))
                  .extract_text()?;
    // index `body` …
}

Table region detection

When you already know a page contains a table and where, scope to the table rect and let extract_tables() focus only on that region:

Python

tables = doc.within(0, (50, 200, 500, 400)).extract_tables()
for t in tables:
    for row in t["rows"]:
        print([c["text"] for c in row["cells"]])

Coordinate reference

PDF uses a bottom-left origin, measured in points (1 pt = 1/72 inch). A Letter-size page is (0, 0, 612, 792). To target the top 1-inch band, write:

(x, y, w, h) = (0, 792 - 72, 612, 72)
             = (0, 720,      612, 72)

If you’re coming from an image-coordinate world (top-left origin), flip y accordingly.

To get the actual MediaBox of a page before calculating:

Python

doc = PdfDocument("doc.pdf")
mb = doc.page_media_box(0)       # (llx, lly, urx, ury)

Rust

let mb = editor.get_page_media_box(0)?;   // [f32; 4]

Go / C# — in-rect helpers

While Go and C# don’t yet expose the fluent within() chain, the underlying lower-level methods are the same:

Method Go C#
Text in rect doc.ExtractTextInRect(page, x, y, w, h) doc.ExtractTextInRect(page, x, y, w, h)
Words in rect doc.ExtractWordsInRect(page, x, y, w, h) (not yet wrapped)
Images in rect doc.ExtractImagesInRect(page, x, y, w, h) (not yet wrapped)

For patterns that need multiple extraction types against the same rect in Go or C#, keep the rect in variables and call the helpers sequentially. The fluent surface will follow once the editor API stabilises.