DEV Community

PARITOSH
PARITOSH

Posted on

Spend Review: I read my friend's bank statement so she never has to

This is a submission for the Hacktoberfest Weekend Challenge: Build for a Friend

What I Built

I built this for my friend Sagrika, who spends like the money is not real and then
arrives at the end of the month genuinely puzzled about where it went. Not reckless,
exactly just a hundred small decisions that never felt like decisions, and no way to
see them stacked up. Her bank sends her a statement every month. She has never once
read it, and having now read one myself, I understand why.

Every Indian bank hands you a statement and calls it insight. HDFC's is a 342-row
.xls where the first 20 rows are your address, the transaction you care about is
described as UPI-SOMTHING HOSPITALITY PVT-Q6245659728@YBL-YESB0YBLUPI-645845694696-PAID
VIA SUPERMONEY
, and nothing anywhere tells you that you spent ₹6,755 on food.

The usual fix is to upload the statement to a budgeting site. That is the part I
would not do. A bank statement is a complete record of where you were and who you
paid for six months — it is not a file to hand to a free web service in exchange for
a pie chart.

Spend Review is a single-file Streamlit app that reads the statement, finds the
real transaction table inside the bank's formatting, and sorts six months of spending
into 14 categories. It holds nothing. The file is parsed in memory and gone when you
close the tab.

Upload, and you get:

  • Total spent, total received, transaction count
  • Spend per category with each category's share
  • Top 20 payees, with the bank's narration string cleaned into an actual name
  • A filterable table of every transaction, downloadable as CSV

That's the whole app. It doesn't set budgets, it doesn't send reminders, and it will
never tell her to stop buying things. It just makes six months of small decisions
visible in one screen, which turns out to be the part that was missing.

Demo

Hosted demo: https://spend-review.onrender.com

Free tier, so the first load takes about a minute while the service wakes up — give it
a moment before deciding it's broken. Nothing you upload is stored, by the service or
by me; the file is parsed in memory and dropped when you close the tab.

In the recording: six months of an HDFC statement goes in as the bank exported it,
342 rows of letterhead and footer and all, and 294 categorised transactions come out.
The surprise is not the food row. It's that the subscriptions row is more than twice
as large, spread over fourteen charges small enough that none of them ever felt like
spending money.

Code

GitHub logo Pager-dot / spend-review

Streamlit app that categorises HDFC bank statement spending

Spend Review

A small Streamlit app that reads an HDFC Bank account statement (.xls / .xlsx) and groups the transactions into spending categories.

Live demo: https://spend-review.onrender.com — free tier, so the first load takes about a minute while the service wakes up. Nothing you upload is stored.

Run locally

pip install -r requirements.txt
streamlit run app.py
Enter fullscreen mode Exit fullscreen mode

Then upload your statement in the browser.

What it shows

  • Total spent, total received, transaction count
  • Spend by category, with each category's share
  • Top payees
  • A filterable transaction table, downloadable as CSV

Categories

Categorisation is keyword matching on the transaction narration. The rules live in the RULES dict at the top of app.py — add keywords there to tune it.

Person-to-person UPI transfers fall into a single Transfers to People bucket, since those narrations carry only a name and no merchant information.

Privacy

  • Uploaded statements are parsed in memory and never written…

How I Built It

Streamlit, pandas, and about 200 lines of Python. No model, no API, no database. The
interesting parts were all in the data.

Why Does Open Innovation Matter?

The honest version of my answer is that open innovation let me not use an API at all.

It costs nothing and cannot be taken away. No key, no account, no quota, no
pricing-page change in eighteen months. pip install -r requirements.txt and it runs,
today or in five years, with the Wi-Fi off. Free-tier API keys are the one component
of a weekend project most likely to be dead before anyone else tries to run it.

My Agent Session

Built in an evening with Claude Code. The useful division of labour turned out to be
that it did the archaeology and I did the judgement calls.

It opened the .xls, found the header at row 20, worked out that xlrd was required,
built the keyword rules from the actual narration strings in my statement rather than
from a guess about Indian merchants, and caught the $PORT binding issue before the
first Render deploy instead of after it.

Two moments worth recording. When I asked it to make a public repo it checked what was
staged and grepped the committed history for my account number and card digits before
pushing — the statement was gitignored, but it verified rather than assumed. And when I
said "make sure nothing is stored", it came back with the cache_data decorator it
had itself added two steps earlier, and explained why that was the one thing in the app
that broke the promise. I would not have found that.

Prize Categories

Best Use of Render

Top comments (0)