DocsAPI LogoDocsAPI

OCR for Bank Statements, Checks and Utility Bills: Worked Math

Nupura Ughade
Nupura Ughade
|
June 12, 2025
|
Updated September 28, 2026
|
13 min read
In short

OCR for bank statements reads account details, opening and closing balances, and every transaction row, then proves the read with one sum: opening balance plus credits minus debits must equal closing balance. Lenders add authenticity checks or pull data straight from the bank.

OCR for bank statements turns a PDF or photo into rows of data, then checks its own work with arithmetic: opening balance plus credits minus debits must equal the closing balance. Checks work differently. They carry a magnetic-ink line whose routing number has its own checksum. Utility bills are ordinary text, but utility meter photos are an image problem. This page gives the field lists, worked math and lender checks.

What does OCR for bank statements extract?

OCR for bank statements reads the account header (holder, bank, account number, statement period), the opening and closing balances, and every transaction as a row with a date, description, amount and debit or credit direction. Some banks also print a running balance after each row. The output is JSON or CSV.

FieldCommon trap
Account holder and numberJoint accounts list two names; the number is usually masked
Statement periodRows print dates like 07/17 with no year, so the period supplies it
Opening and closing balanceLabels vary (beginning, ending); "available balance" is a different number
Transaction date and descriptionLong descriptions wrap onto a second line
Amount, debit or creditTwo columns, one signed column, or CR and DR suffixes
Running balanceMany banks print only daily balances

Field names differ by vendor. Microsoft's public schema for its US bank statement model returns BeginningBalance and EndingBalance per account, and Date, Description, CheckNumber, DepositAmount and WithdrawalAmount per transaction. As of the version we read, it has no running balance and no total credits or debits, so confirm what your tool returns.

OCR is for scans and photos; a PDF from the bank's website already holds its text (readable PDF vs image PDF has a two-second test).

Why does bank statement OCR fail, and how do you prove it read the statement right?

It usually fails on table structure, not on letters. Amounts land in the wrong column, rows split at page breaks, and page subtotals or wrapped descriptions become fake rows. You catch this with one sum: opening balance plus credits minus debits must equal the closing balance to the cent. If it misses by one cent, at least one number is wrong.

Table handling is the real gap between engines. In the 500-document OCR-engine set of our benchmark, character-level accuracy on scanned multi-page bank statement tables was 64% for Tesseract 5.x, 79% for PaddleOCR and 91% for DocsAPI. On the separate 1,200-document parser set, bank statement tables scored 76% for Docling, 71% for LlamaParse and 91% for DocsAPI. DocsAPI is our product, so see the full benchmark method. Most engines treat each page as its own table (PDF parser online explains).

The reconciliation check, worked

Here is a made-up August statement. The opening balance on August 1 is 4,250.00, and the bank prints a running balance after each row.

DateDescriptionDebitCreditRunning balance
Aug 3Deposit, card settlement3,120.457,370.45
Aug 5Check 10411,200.006,170.45
Aug 7ACH rent1,850.004,320.45
Aug 12Deposit2,480.006,800.45
Aug 14POS fuel64.186,736.27
Aug 18ACH payroll2,900.003,836.27
Aug 21Deposit1,975.305,811.57
Aug 27Service fee15.005,796.57
Aug 29Check 1042410.755,385.82

Credits: 3,120.45 + 2,480.00 + 1,975.30 = 7,575.75. Debits: 1,200.00 + 1,850.00 + 64.18 + 2,900.00 + 15.00 + 410.75 = 6,439.93. So 4,250.00 plus 7,575.75 minus 6,439.93 = 5,385.82, which matches the closing balance. Now break it three ways:

What OCR got wrongComputed closing balanceGap to the printed 5,385.82
The Aug 12 deposit of 2,480.00 read into the debit column425.824,960.00 too low (twice 2,480.00)
The Aug 21 deposit of 1,975.30 lost at a page break3,410.521,975.30 too low
Rent of 1,850.00 read as 1,650.005,585.82200.00 too high

Any gap sends the statement to review. If a running balance is printed, also test each row: previous balance, minus the debit or plus the credit, must equal the printed one. In the third case, row 3 expects 4,520.45 but the bank printed 4,320.45, which points to the bad row.

What the check cannot tell you

  • It proves the numbers agree, not that the statement is genuine. A careful edit can keep the arithmetic consistent (see bank statement fraud detection).
  • A right amount under a truncated description passes the sum, yet the description decides whether a large deposit needs explaining.
  • One closing balance should also equal the next opening balance, which multi-account bank statement OCR covers.

How do lenders verify bank statements automatically?

Lenders use three routes, often together. Software reads the statement and checks its arithmetic and required fields. Forensic checks look for signs of editing, such as font differences, suspiciously round numbers, typos and totals that do not add up (Ocrolus lists these). Or, with the borrower's permission, the lender pulls data straight from the bank and skips the document.

For mortgages sold to Fannie Mae, section B3-4.2-01 says a statement must show the institution, the borrower as account holder, the last four digits of the account number, the period, all deposits and withdrawals, and the ending balance. A purchase needs the most recent full two-month period, a refinance one month, and a statement over 45 days old needs supplemental bank-generated documentation. The guide also accepts direct verification by a vendor when the borrower authorizes it.

Section B3-4.2-02 defines a large deposit as a single deposit above 50% of total monthly qualifying income. If the source (payroll, Social Security, an IRS refund, a transfer between verified accounts) is printed on the statement, nothing more is needed. These are mortgage rules; other lenders set their own. OCR reads the fields so rules can run; it does not decide whether a deposit is acceptable (verification of assets OCR works the rule).

What do OCR for underwriters and OCR for bank statement analysis need to deliver?

Clean rows plus a few computed numbers: verified balances, every deposit with its full description, fee and overdraft counts, and a flag on anything the software doubted. Extraction reads the statement. Analysis, the next step, categorizes transactions and computes income, average balance and overdraft signals. It is only as good as the rows under it.

Underwriter asksWhat breaks it
Is income steady?Own-account transfers counted as income (cash flow underwriting OCR)
Any overdrafts or NSF?Shortfalls covered by a linked account leave no fee (NSF overdraft detection OCR)
Was this data known at decision time?Training on data the model could not have had (real-time bank statement processing)

Small error rates add up. The bank statement OCR pricing post estimates 100 to 200 fields on a multi-page statement. At 150 fields and 99% field accuracy, the chance of zero errors is 0.99 to the power of 150, about 0.22 (assuming independent errors), so the reconciliation check and a review queue matter more than a headline accuracy number. More: automated bank statement analysis and OCR for lending and underwriting.

How does OCR for checks read a bank check?

OCR for checks reads two zones. The face holds the payee, the amount in numbers and in words, the date, the memo and the signature. The bottom line, the MICR line, holds the routing number, account number and check number in magnetic ink. OCR for bank checks is safest when the routing number is validated with its own checksum.

FieldWhat to validate
Amount in numbers and in wordsThey must agree; if not, a person decides
DateA bank need not pay a check presented over six months after its date (UCC 4-404), so flag old dates
Routing number (MICR)Nine digits that pass the checksum below
Amount (MICR)Added later in processing, so an unprocessed check often has none; use the face

What is the MICR line?

MICR means magnetic ink character recognition. Regulation CC (12 CFR 229.2) defines the MICR line as numbers printed near the bottom of a check in magnetic ink under ANSI standard X9.13, such as the routing, account and check numbers. US checks use the E-13B font: 10 digits and four symbols (transit, on-us, amount, dash). Bank scanners read the magnetism. A phone photo has only the picture, so OCR must recognize E-13B shapes from pixels.

Layout varies by check style (Microsoft's sample puts the check number first), so read fields by the symbols around them. The US Treasury's OTCnet check capture flags a "Reject Characters Detected" error when the MICR line cannot be read, offers a rescan for skewed or upside-down images, and lets only a supervisor or lead operator key in a corrected line. Never guess silently.

The routing number checksum, worked

A US routing number has nine digits: a four-digit Federal Reserve routing symbol, a four-digit institution identifier and a check digit. The Federal Reserve Bank of New York announced the check digit in Circular 8203 (October 19, 1977) as the last digit of the routing number field, computed "modulus-10, weights 3, 7, 1". Multiply the digits by 3, 7, 1, 3, 7, 1, 3, 7, 1, add the products, and the total must be a multiple of 10. We use 021000021 only for the arithmetic, not to say whose it is.

Position123456789
Digit021000021
Weight371371371
Product01410000141

The products add up to 30, so the number is valid. Here is what the test catches:

What OCR didNumberTotalResult
Correct read02100002130Pass
Last digit misread (1 as 2)02100002231Fail
Made-up valid number01610000420Pass
Same, with 1 and 6 swapped06110000450Pass (missed)

We brute-forced it in Python. Across 20,000 random valid numbers, all 1,620,000 single-digit errors failed the test, and adjacent swaps were missed only when the two digits differ by exactly 5 (1 and 6, 2 and 7). If one digit is unreadable and you know its position, exactly one of the ten digits passes, so the checksum can repair it. With two uncertain positions, ask a person.

def routing_ok(r):
    if len(r) != 9 or not r.isdigit():
        return False
    weights = [3, 7, 1] * 3
    return sum(int(d) * w for d, w in zip(r, weights)) % 10 == 0

print(routing_ok("021000021"))  # True
print(routing_ok("021000022"))  # False
print(routing_ok("123456789"))  # False

The last line is the sample routing number on Microsoft's check schema page, which fails (its products total 159). A pass proves the number is well formed, not that it is assigned or that the check is genuine, so look it up in the Federal Reserve's E-Payments Routing Directory. Passport MRZ check digits work similarly (details).

Can OCR for utility bills prove where someone lives?

OCR for utility bills can reliably read the name, service address and bill date. Whether that proves an address depends on who is asking: the allowed bill age, and whether the service or mailing address counts, differ by requester. OCR also cannot tell a genuine bill from a forged one.

FieldTrap
Service addressWhere service is supplied; can differ from the mailing address
Mailing addressMay be a PO box; California's DMV also wants a physical address
Bill dateStarts the age clock for most requesters; confused with the due date or period end

There is no single date rule. Canada's FINTRAC lists a utility bill as a reliable source for name and address and says only that the information must be valid and current, with no day count. California's DMV accepts home utility bills and bank records, and asks for two different documents. Windows of three to six months are common in KYC and some regions use two (see proof of address verification, which also covers address matching and file forensics).

Example: a bill dated July 15, 2026, checked on September 21, 2026, is 68 days old. It passes a 90-day rule and fails a 60-day rule. If OCR reads the due date as the bill date, an old bill looks newer than it is, so label every date and let a per-customer policy set the window.

Is OCR for utility meter readings the same problem?

No. A utility bill prints its numbers as text, so OCR reads them. OCR for utility meter readings starts from a photo of a physical meter, with glare, dirt, tilt and digit wheels caught mid-turn. That is mostly image recognition: find the counter, straighten it, recognize the digits, and reject photos that cannot be read.

The clearest evidence is a published study by Laroca and colleagues (IEEE Access, 2021). Their Copel-AMR dataset holds 12,500 meter images taken in the field by an energy company's employees, and 2,500 (20%) cannot be read at all because of occlusion or faulty meters. On their data, rejecting low-confidence readings gave recognition of 99% or better, filtering out 98.9% of illegible meters while accepting 99.82% of legible ones. That is one utility's photos, not a guarantee for yours.

Electromechanical meters have digit wheels that can be caught mid-turn, so the authors follow the utility's protocol of labeling the lower digit (a wheel between 4 and 5 counts as 4). Models trained on general text data are likely to fail on rotating digits. What works:

  1. Use smart meter or utility account data if available, and skip the photo.
  2. If you need photos, use a detect, straighten and recognize pipeline built for meters, not general document OCR.
  3. Reject unreadable photos and ask for another. Do not guess.
  4. Validate: a cumulative register only counts up, so a lower reading is a misread or a rollover.

DocsAPI's supported document list includes utility bills, not meter photos, so for meters look at a meter-specific model.

Do OCR for financial statement extraction and OCR for reconciling transactions work the same way?

They share one idea: extract the numbers, then test that they tie. OCR for financial statement extraction reads balance sheets, income statements and cash flow statements into line items and checks that subtotals add up and assets equal liabilities plus equity. OCR for reconciling transactions matches bank statement rows to your ledger and explains every difference.

Financial statements

LlamaIndex defines financial statement extraction as turning income statements, balance sheets and cash flow statements into machine-readable data. The hard part is layout: a prior-year column beside the current one, nested tables and footnotes.

Take a made-up balance sheet: cash 18,400, receivables 26,150, inventory 12,300 and equipment 43,150 total 100,000. Liabilities of 21,700, 15,000 and 28,300 total 65,000, and with owner's equity of 35,000 the sum is also 100,000: assets equal liabilities plus equity, the accounting equation in OpenStax's textbook. If OCR reads receivables as 26,750, assets become 100,600, off by 600, so the statement goes to review.

Reconciling transactions

OpenStax describes a bank reconciliation as the report that explains the differences between the bank's balance and your own records. Bank-side items are deposits in transit and outstanding checks (you recorded them, the bank has not). Book-side items are service charges, NSF checks and interest (the bank recorded them, you have not).

Take the August statement above. The bank's closing balance is 5,385.82. Your books show 5,914.32 before you record the 15.00 service fee. A deposit of 1,200.00 made on August 31 posts at the bank in September, and check 1043 for 686.50 has not cleared. Adjusted bank balance: 5,385.82 plus 1,200.00 minus 686.50 = 5,899.32. Adjusted book balance: 5,914.32 minus 15.00 = 5,899.32. They tie.

OCR's job is clean rows: signed amounts, ISO 8601 dates, full descriptions and check numbers (see data normalization for extracted documents). Match on check number and amount first. Bank rows with no ledger match suggest book-side items; ledger entries with no bank match suggest bank-side items. Credit card statements follow the same logic.

What to do next

  • Lender or underwriter: run the reconciliation check on every statement, apply your own deposit and statement-age rules, and add file forensics or direct bank data for risky files. Our bank statements page shows what our product extracts.
  • Bookkeeper: treat unmatched rows as reconciling items, not errors.
  • Taking checks: validate the checksum and directory lookup, compare numbers with words, flag old dates, and keep a human correction step. We do not list check images as a supported document type.
  • Verifying addresses: extract every date and apply the requester's window.
  • Reading meters: smart meter data first, otherwise a model that rejects bad photos.

Choosing a vendor? Test 50 of your own documents (how to measure OCR accuracy explains scoring): a 12-page statement, extracted totals against printed totals, a slightly angled phone photo, field-level confidence scores, and a written answer on training use of your documents.

Sources and how we checked this

We opened each source below and used only what the page states. All arithmetic was run in Python 3 with exact decimals. DocsAPI is our product and the benchmark is our own test, so run your own.

Limits: we could not open the ABA's Routing Number Policy, so the nine-digit structure rests on Wikipedia's summary; the weights come from the Federal Reserve circular. Fannie Mae rules cover mortgages sold to Fannie Mae. The date windows are examples from two public sources. We did not test any vendor's check or meter product. This is not legal advice: the rule's owner, not OCR, decides whether a document satisfies a lending or KYC rule.

Common questions

Frequently asked questions

Often you do not need OCR at all. A PDF downloaded from a bank's website usually has the text inside the file, so software can read it directly and the work is table extraction. OCR is for scans and photos, where the page is only a picture. If you cannot select the text with your cursor, it is an image PDF.

Yes, if the whole page is in frame, flat and sharp, but expect more errors than from a PDF. Microsoft's Document Intelligence documentation asks for one clear photo or high-quality scan per document and a minimum text height of 12 pixels on a 1024 by 768 image, about 8-point text at 150 dots per inch. Run the reconciliation check on every photo.

On a statement you receive as the account holder, a credit is money added to the account (a deposit) and a debit is money taken out (a withdrawal or fee). Some statements use two columns, some use one signed column, and some add CR or DR after the amount. OCR must map each layout to a consistent sign before the reconciliation sum works.

It depends on the lender and the loan. For mortgages sold to Fannie Mae, the Selling Guide asks for the most recent full two-month period (60 days, or the most recent quarter) on a purchase and one month on a refinance. Other lenders, including small business lenders, set their own rules, so check the lender's checklist rather than assuming.

Less, but not never. With borrower authorization, Fannie Mae's guide accepts direct verification through an asset verification vendor, which skips the document. When the borrower does not connect an account, the lender falls back to uploaded statements, and that is where OCR and the checks on this page apply.

No. The reconciliation check proves the numbers agree with each other. A careful forger can edit a statement and keep the arithmetic consistent. Authenticity needs separate checks on how the file was built and edited, and for high-risk files, direct data from the bank. OCR reads what is on the page; it does not know whether the bank issued it.

It can, with lower accuracy. In our benchmark, DocsAPI scored 78% at character level on handwritten forms of mixed neatness, against 73% for PaddleOCR and 61% for Tesseract 5.x. That is why the amount in numbers should be compared with the amount in words, and any disagreement should go to a person.

Requesters often accept either, so ask which they prefer. California's DMV lists both home utility bills and bank records, and wants two different documents. A utility bill shows where service is supplied. A bank statement shows where the bank mails the statement, which may not be a residence. Check the date window and address type each requester wants.

Yes. The UFPR-AMR dataset has 2,000 annotated meter images and is public. The larger Copel-AMR dataset has 12,500 field images, including 2,500 unreadable ones, and is available to the research community after registering and accepting its terms. The Copel-AMR images come from a Brazilian energy company's field staff.

The checksum only tests that nine digits are well formed. About 1 in 10 random nine-digit strings passes; in a simulation of 200,000 random strings we saw 9.96% pass. So a pass does not show the number belongs to a bank. Look it up in the Federal Reserve's E-Payments Routing Directory. Neither test shows the check itself is genuine.

Use the bank's original PDF whenever you can: digital statements carry a text layer that tools for OCR bank statements read almost perfectly, while scans and photos are where errors creep in. Then check the running balance on every row and compare the opening and closing balances with the statement summary.

Software that reads bank statements, extracts every transaction and then analyses them: payroll and other income deposits, recurring bills, overdraft and NSF fees, and cash-flow trends. Lenders use an automated bank statement analyser to underwrite faster, but it should only analyse statements whose balances have reconciled.

Scan at 300 DPI, keep every page including ones that look blank, and avoid angled phone photos. Account statement OCR on a clean 300 DPI scan works well, but keep the running-balance check, because one misread digit changes every balance after it.

Nupura Ughade

Content Marketing Lead, DocsAPI

Nupura Ughade creates clear, insightful content on OCR, document AI, and fintech. She combines technical depth with real-world finance use cases to help engineers and operations leaders navigate digital transformation with confidence.

Want to see it on your own documents?

Try our free OCR tool in your browser, or book a demo to see how DocsAPI reads the document types covered in this guide.