← Back to blog
·8 min read

Yes Bank Statement Parser: Extract Structured Data with AI

Parse any Yes Bank statement—savings, salary, or current account—into structured JSON with AI. Handles all PDF formats, multi-page exports, and edge cases.

yes bankbank statement parserai extractionindian bankingfintech apidocument aitypescript

Yes Bank is one of India's fastest-growing private sector banks, with over 1,100 branches and a strong digital-first customer base. If you're building a lending app, expense tracker, KYC pipeline, or financial AI agent for Indian users, Yes Bank statements will show up in your document queue — often in formats that trip up legacy OCR tools.

This guide shows you how to extract structured JSON from any Yes Bank statement using Lekha's AI extraction API, with full TypeScript examples and coverage of the edge cases unique to Yes Bank's PDF exports.

What Makes Yes Bank Statements Tricky

Yes Bank generates PDFs through at least four different paths, each with a distinct layout:

| Statement Type | Format Notes | | ------------------------ | ----------------------------------------------------------------- | | Internet banking PDF | Clean tabular layout, but column widths vary by transaction count | | YES PAY / app export | Condensed single-column style, no header per page | | Branch-printed statement | Scanned image PDF, often with watermarks and stamp | | Credit card statement | Separate format: billing cycle summary + itemised spend | | YES Prosperity (salary) | High-volume transactions, sometimes 10+ pages |

Traditional regex-based parsers break on format switches. A model trained only on one variant will silently corrupt data when customers upload another. Lekha handles all four variants through the same API endpoint — you send the PDF, you get JSON.

Quickstart: Parse a Yes Bank Statement

Install the Lekha SDK and set your API key:

bun add @lekhadev/sdk

or: npm install @lekhadev/sdk

import Lekha from "@lekhadev/sdk";
import { readFileSync } from "fs";

const lekha = new Lekha({ apiKey: process.env.LEKHA_API_KEY! });

const pdf = readFileSync("yes-bank-statement.pdf");

const result = await lekha.extract({ document: pdf, type: "bank_statement", });

console.log(result.data);

That's it. Lekha auto-detects that it's a Yes Bank document and routes it to the correct extraction model. No bank-specific flags needed.

The Structured JSON Response

A successful extraction returns a response shaped like this:

{
  success: true,
  data: {
    bank: "Yes Bank",
    account_holder: "Priya Sharma",
    account_number: "XXXXXXXXXXXX3471",
    account_type: "savings",
    ifsc: "YESB0000123",
    branch: "Andheri West, Mumbai",
    currency: "INR",
    period: {
      from: "2025-04-01",
      to: "2025-06-30"
    },
    opening_balance: 42180.50,
    closing_balance: 61940.75,
    total_credits: 185000.00,
    total_debits: 165239.75,
    transactions: [
      {
        date: "2025-04-03",
        description: "NEFT CR-HDFC000012-RAHUL MEHTA",
        amount: 50000.00,
        type: "credit",
        balance: 92180.50,
        reference: "N2504031234567"
      },
      {
        date: "2025-04-05",
        description: "UPI/P2M/SWIGGY/9876543210",
        amount: 847.00,
        type: "debit",
        balance: 91333.50,
        reference: "UPI202504051234"
      }
      // ... all transactions
    ]
  }
}

All amounts are numbers (never strings), all dates are ISO 8601 (YYYY-MM-DD), and account numbers are masked to match the format Yes Bank uses in the source PDF.

Handling Yes Bank's Common Edge Cases

Password-Protected PDFs

Yes Bank's internet banking portal lets users download encrypted statements. Pass the password in the request:

const result = await lekha.extract({
  document: pdf,
  type: "bank_statement",
  password: "PRIYA19850312", // DOB format: common default
});

Lekha decrypts, extracts, and discards the password — no plaintext storage.

Multi-Page Salary Account Statements

YES Prosperity salary accounts often have 200+ transactions a month. The extraction handles pagination internally:

const result = await lekha.extract({
  document: largePdf, // 12-page statement
  type: "bank_statement",
});

console.log(result.data.transactions.length); // 247 — all pages merged

Transactions are returned in chronological order, de-duplicated across page overlaps (Yes Bank repeats the last row of each page as the first of the next).

Credit Card Statements

Yes Bank credit card statements have a different schema — billing cycle, minimum due, reward points. Lekha detects and routes these automatically:

const result = await lekha.extract({
  document: creditCardPdf,
  type: "bank_statement", // same endpoint — auto-routes to credit card schema
});

// result.data.account_type === "credit_card" // result.data.credit_limit, result.data.min_due, result.data.reward_points

Building a Yes Bank Income Verification Agent

Here's a practical pattern — an income verification agent that checks salary credits and flags unusual months. Useful for lending, rental KYC, and employee verification workflows:

import Lekha from "@lekhadev/sdk";
import Anthropic from "@anthropic-ai/sdk";

const lekha = new Lekha({ apiKey: process.env.LEKHA_API_KEY! }); const claude = new Anthropic();

async function verifyIncome(statementPdf: Buffer) { // Step 1: extract structured data const { data } = await lekha.extract({ document: statementPdf, type: "bank_statement", });

// Step 2: isolate salary credits const salaryCredits = data.transactions.filter((tx) => /(salary|sal|payroll|neft cr.*payroll)/i.test(tx.description), );

// Step 3: group by month const monthlyCredits: Record = {}; for (const tx of salaryCredits) { const month = tx.date.slice(0, 7); // "YYYY-MM" monthlyCredits[month] = (monthlyCredits[month] ?? 0) + tx.amount; }

// Step 4: ask Claude to reason about the income pattern const response = await claude.messages.create({ model: "claude-sonnet-4-6", max_tokens: 512, messages: [ { role: "user", content: Analyse this monthly salary data and flag any anomalies. Account holder: ${data.account_holder} Period: ${data.period.from} to ${data.period.to} Monthly salary credits: ${JSON.stringify(monthlyCredits, null, 2)}

Return JSON: { consistent: boolean, avg_monthly_salary: number, anomalies: string[] }, }, ], });

return JSON.parse(response.content[0].text); }

// Usage const result = await verifyIncome(statementPdf); console.log(result); // { // consistent: true, // avg_monthly_salary: 85000, // anomalies: ["March 2025: no salary credit detected"] // }

This pattern is production-ready for lending pre-screening — combine it with Form 16 extraction to cross-validate declared income against bank credits. See the Form 16 parsing guide for how to layer these signals.

Categorising Transactions for Expense Analysis

Yes Bank UPI and NEFT descriptions follow predictable patterns. Lekha's extraction preserves the raw description string so your downstream logic or AI layer can categorise:

const CATEGORIES: Record = {
  food_dining: /swiggy|zomato|upi.*restaurant|hotel/i,
  shopping: /amazon|flipkart|myntra|meesho/i,
  utilities: /bescom|msedcl|airtel|jio|bsnl/i,
  rent: /rent|lease|neft.*housing/i,
  emi: /emi|loan|repay|nach.*emi/i,
  salary: /salary|sal|payroll/i,
};

function categorise(description: string): string { for (const [category, pattern] of Object.entries(CATEGORIES)) { if (pattern.test(description)) return category; } return "other"; }

const categorised = data.transactions.map((tx) => ({ ...tx, category: categorise(tx.description), }));

For more nuanced categorisation (especially mixed Hindi-English descriptions from branch-generated statements), pass the transactions to Claude with a categorisation prompt — the same approach used in the LangChain integration guide.

Integrating into an API Route (Next.js)

// app/api/verify-statement/route.ts
import { NextRequest, NextResponse } from "next/server";
import Lekha from "@lekhadev/sdk";

const lekha = new Lekha({ apiKey: process.env.LEKHA_API_KEY! });

export async function POST(req: NextRequest) { const formData = await req.formData(); const file = formData.get("statement") as File;

if (!file) { return NextResponse.json( { success: false, error: { code: "missing_file", message: "No statement uploaded" }, }, { status: 400 }, ); }

const bytes = await file.arrayBuffer(); const pdf = Buffer.from(bytes);

const result = await lekha.extract({ document: pdf, type: "bank_statement", });

if (!result.success) { return NextResponse.json(result, { status: 422 }); }

return NextResponse.json({ success: true, holder: result.data.account_holder, period: result.data.period, avg_monthly_balance: computeAvgBalance(result.data.transactions), transaction_count: result.data.transactions.length, }); }

function computeAvgBalance(txs: { balance: number }[]): number { if (!txs.length) return 0; return txs.reduce((sum, tx) => sum + tx.balance, 0) / txs.length; }

Try this in the Lekha playground before wiring it into your app — paste your API key and upload a sample statement to inspect the raw JSON output.

Accuracy and Format Coverage

| Statement Variant | Extraction Accuracy | | ---------------------------------- | ------------------- | | Internet banking PDF (tabular) | 99.1% | | YES PAY app export | 98.4% | | Branch-printed (scanned) | 96.2% | | Credit card statement | 98.8% | | YES Prosperity salary (multi-page) | 98.9% |

Accuracy measured on transaction amount, date, and description across 500 real-world Yes Bank statements per variant. Scanned PDFs are lower due to watermarks and stamp artefacts — Lekha's vision model handles these better than any OCR pipeline, but image quality remains the ceiling.


FAQ

Does Lekha support Yes Bank credit card statements? Yes. Yes Bank credit card PDFs are automatically detected and parsed into a different schema from savings/current accounts — including credit limit, minimum due, reward points, and itemised transactions. Use the same bank_statement type in your request. What if the Yes Bank PDF is password protected? Pass the password field in your extract request. Lekha uses it to decrypt the PDF, extracts the content in memory, and never persists either the password or the decrypted document. This is compliant with India's DPDP Act requirements for data minimisation. Can I extract 6 months of Yes Bank statements at once? Lekha processes one PDF per request, but you can fan out multiple requests concurrently. If you're batch-processing hundreds of statements, see the batch processing guide for concurrency limits, retry logic, and progress tracking patterns. How does Lekha handle Yes Bank's Hindi transaction descriptions? Yes Bank branch-generated statements sometimes contain mixed Hindi-English descriptions (e.g. for RTGS transfers). Lekha's vision model reads Devanagari natively and returns the description in Unicode — downstream categorisation with Claude handles both scripts without extra configuration.

Ready to add Yes Bank statement extraction to your product? Create a free Lekha account and get 50 extractions free — no credit card required. The full API reference is at lekhadev.com/docs.