DEV Community

jesroff rouk
jesroff rouk

Posted on

Local Receipt Extractor

Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle Submission 💸

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle

What I Built

A small command-line tool that reads receipt and invoice images and returns clean, structured data: vendor, date, total, currency, and expense category.

Who would pay for it: freelancers and small-business owners who spend every quarter digging through photos and screenshots of receipts before tax season. A bookkeeper handling several clients' receipts could use it too.

The problem it solves: manual data entry is slow and tedious, and receipts contain client names and payment details that people don't want to upload to a cloud service. This tool turns a folder of messy images into structured data, and everything stays on the user's machine.

Demo

Example output:

{"file": "receipt_01.jpg", "vendor": "Starbucks", "date": "2024-03-12", "total": 8.45, "currency": "USD", "category": "meals"}
Enter fullscreen mode Exit fullscreen mode

Code

Local Receipt Extractor

A tiny script that reads receipt images with an open-weight vision model running locally via Ollama and returns structured data: vendor, date, total, currency, and expense category.

No cloud API, no per-page fees, and receipts never leave your machine.

Setup

# 1. Install Ollama: https://ollama.com
ollama pull qwen2.5vl:7b

# 2. Install dependencies
pip install ollama pydantic
Enter fullscreen mode Exit fullscreen mode

Usage

python receipt_extract.py receipt.jpg
python receipt_extract.py ./receipts --csv results.csv
python receipt_extract.py ./receipts --model gemma3:4b
Enter fullscreen mode Exit fullscreen mode

Example output (one JSON line per receipt):

{"file": "receipt.jpg", "vendor": "Starbucks", "date": "2024-03-12", "total": 8.45, "currency": "USD", "category": "meals"}
Enter fullscreen mode Exit fullscreen mode

Why open models?

  • Privacy: receipts contain client names and payment details; nothing is uploaded.
  • Cost: free to run, no per-receipt charges.
  • Offline: works with no internet after the model is downloaded.
  • Swappable: change the model…

How I Built It

  • Ollama runs the model locally.
  • Qwen2.5-VL (7B), an open-weight vision model, reads the receipt image directly, with no separate OCR step.
  • Pydantic defines the output schema, and Ollama's structured output forces the model to return valid JSON that matches it, so there's no fragile text parsing.
  • Python, in a single script of about 80 lines.

Usage is one line:

python receipt_extract.py ./receipts --csv results.csv
Enter fullscreen mode Exit fullscreen mode

The model is a command-line flag (--model gemma3:4b), so swapping models needs no code changes.

Why Does Open Innovation Matter?

  • Privacy: receipts contain client names, addresses, and payment details. With a local open-weight model, none of that is uploaded to a server I don't control. A closed API couldn't offer that.
  • Cost: there are no per-page fees. Running 1,000 receipts costs the same as running 1.
  • Offline: after the one-time model download, it works with no internet.
  • Swappable: I can try a different model with one flag, or fine-tune on a specific receipt format later.

Where it fell short: small local models can misread blurry or unusual receipts. A larger closed model would probably do better on those. For a tool that handles sensitive financial documents, I think the privacy and zero-cost trade is worth it, as long as the output is spot-checked before it goes to an accountant.

Top comments (0)