# Turn Scanned Documents into Searchable, Structured Data ![banner](https://articles.aux4.blog/data/posts/aux4/turn-scanned-documents-into-searchable-data/banner.png) ## Introduction A folder of scanned receipts is data you can't actually use. The numbers are locked inside pixels — you can't search them, total them, or look anything up. The goal here is to take a single scanned receipt image and turn it into a record you can query with SQL-like expressions. We'll OCR the image with `aux4/image`, archive it as a searchable PDF, pull the text back out with `aux4/pdf`, and store the structured result in `aux4/repository`. ## Install the packages ```bash aux4 aux4 pkger install aux4/image-text aux4/pdf aux4/repository ``` `aux4/image-text` adds OCR commands (`text`, `pdf`) under the `image` profile and relies on Tesseract, which it installs for you. ## Step 1: read text straight off an image The fastest path from pixels to text is `aux4 image text`. Point it at an image and it prints what it recognizes to stdout: ```bash aux4 image text receipt.png ``` ```text GROCERY MART 742 Market Street Milk 3.99 Bread 2.49 Eggs 4.25 Total 10.73 ``` The page-segmentation mode matters for odd layouts. A single line of text — a label, a SKU — reads better with `--psm 7`: ```bash aux4 image text label.png --psm 7 ``` ```text SKU-48217 ``` Use `--lang` to OCR a different language (`--lang eng` is the default; install extra Tesseract language packs for others). ## Step 2: archive the scan as a searchable PDF Raw text is great for a pipeline, but for archiving you usually want to keep the original image *and* be able to search it. `aux4 image pdf` does both — it lays an invisible OCR text layer over the image and writes a PDF: ```bash aux4 image pdf receipt.png --output receipt ``` ```text receipt.pdf ``` The output name is given without the `.pdf` extension. Multi-page documents are just multiple inputs, one `--input` per page: ```bash aux4 image pdf \ --input page1.png --input page2.png --input page3.png \ --output statement ``` You now have `statement.pdf` — looks like the scan, but every word is selectable and searchable. ## Step 3: pull structure back out with aux4/pdf Once you have a PDF — whether scanned or a real fillable form — `aux4/pdf` turns it back into data. The simplest command extracts plain text: ```bash aux4 pdf text receipt.pdf ``` ```text GROCERY MART 742 Market Street Milk 3.99 Bread 2.49 Eggs 4.25 Total 10.73 ``` For fillable forms, `aux4 pdf parse` is the powerful one: it returns a JSON array of pages, each with its text *and* every form field — name, type, value, options for dropdowns, and a bounding box (`ref`): ```bash aux4 pdf parse invoice.pdf ``` ```json [ { "page": 1, "text": "Please enter your name: [Field:Name] ...", "fields": [ { "name": "Name", "alternativeText": "", "value": "", "type": "TextField", "ref": { "x": 202.468, "y": 587.91, "width": 209.821, "height": 22 } }, { "name": "Dropdown2", "alternativeText": "", "value": ["Choice 1"], "type": "Dropdown", "options": ["Choice 1", "Choice 2", "Choice 3", "Choice 4"], "ref": { "x": 71.6528, "y": 524.831, "width": 72.0002, "height": 20 } } ] } ] ``` A couple of neighbors worth knowing: `aux4 pdf count` returns the page count, `aux4 pdf search --term ` finds a term with its page and coordinates, and `aux4 pdf image --page 2 --image page2.png` renders a page back to an image. (There's no `pdf render` — it's `pdf image`.) ## Step 4: store the structured record Now the payoff: persist the extracted fields somewhere you can query them. `aux4/repository` is a local JSON document store backed by SQLite — no server, no schema migrations. Each "repository" is a table; it's created the first time you write to it, and the database file defaults to `.local.db` in the current directory. After shaping the OCR/parse output into a clean object (with `jq`, or by hand), write it in: ```bash aux4 repository write invoices --id inv-001 \ --data '{"vendor":"Acme","total":129.50,"date":"2025-12-17"}' \ --metadata '{"source":"scan","ocr":"tesseract"}' ``` ```text inv-001 ``` The `id` becomes the primary key, and writes are upserts — re-running with the same id updates the record instead of duplicating it. You can also pipe JSON straight in and let it generate a UUID: ```bash echo '{"vendor":"Globex","total":58.20}' | aux4 repository write invoices ``` ## Step 5: query like a database This is what the whole pipeline was for. `aux4 repository find` takes a SQL-like expression where bare field names resolve into the stored JSON: ```bash aux4 repository find invoices --expr "total > 100 and vendor = 'Acme'" ``` ```json [ { "id": "inv-001", "vendor": "Acme", "total": 129.50, "date": "2025-12-17" } ] ``` It supports the comparisons you'd expect (`=`, `!=`, `<`, `>`, `<=`, `>=`), `like` for fuzzy text, `and`/`or`, and parentheses: ```bash aux4 repository find invoices --expr "vendor like '%Acme%' or total < 60" aux4 repository read invoices --id inv-001 # fetch one by id ``` Your folder of dead scans is now a searchable ledger. ## Conclusion The path from scan to searchable data is four short hops: 1. **`aux4 image text`** — OCR the image to plain text. 2. **`aux4 image pdf`** — archive it as a searchable PDF. 3. **`aux4 pdf parse` / `pdf text`** — extract text and form fields as JSON. 4. **`aux4 repository write` / `find`** — store the structured record and query it. Every step is a small, focused command, so you can stop at any point — just OCR, just archive, or go the whole way to a queryable store. Point it at receipts, invoices, forms, or a backlog of scanned paperwork, and the documents finally become data. ## See Also - [aux4/image-text](https://hub.aux4.io/r/public/packages/aux4/image-text) - [aux4/pdf](https://hub.aux4.io/r/public/packages/aux4/pdf) - [aux4/repository](https://hub.aux4.io/r/public/packages/aux4/repository)