ForHosting KIT · OCR & Data Extraction

Read a bank statement

A PDF bank statement is a table pretending to be a document, and pulling transactions out of it by hand is the single most tedious part of reconciliation. This endpoint reads a statement — any bank's layout — and returns each transaction's date, description and amount as structured JSON, ready to reconcile or categorize.

● BetaPer request + per page$0.010
Use it from WebAPIEmailApp soonTelegram soon

Run this on our servers with your account. Free tools run in your browser; this one bills your KIT balance per the price above.

Why statements are harder than they look

Every bank formats its statement PDF differently: some list a running balance column, some split debits and credits into separate columns, some wrap long merchant descriptions onto a second line that a naive text extractor treats as an unrelated row. Multiply that by a business with accounts at three or four banks, or an accountant handling dozens of clients, and manual transcription stops being a task and becomes a bottleneck. Even copy-pasting from a PDF viewer often scrambles the column order, which is why so many people still end up retyping numbers by hand.

Who feeds statements through this

Bookkeepers and accountants reconciling client accounts without native bank feeds, personal-finance apps letting users import history from any bank by uploading a PDF, auditors sampling transaction history from statements rather than live feeds, and underwriting tools that need a structured read of cash flow from bank statements submitted as part of a loan application.

What the output looks like

Send the statement, get a task_id immediately, and the completed job returns account details, statement period, and every transaction line — date, description, amount, and running balance where present — as an ordered JSON array, ready to load into a ledger or a reconciliation script without re-parsing a PDF table.

Where it sits in a reconciliation pipeline

Because it's asynchronous and priced per page, a one-page statement with a handful of transactions costs a fraction of a twelve-page annual statement, scaling fairly with what's actually being read: a reconciliation tool ingests uploaded statements, submits each on receipt, and the webhook delivers the transaction list at the moment it's ready to be matched against the general ledger.

Reading a format never designed to be read by code

Bank statements were designed for a person scanning a printed page, not for a program parsing structured data — that's the root of the difficulty. Column alignment that looks obvious to a human eye carries no explicit structure in the underlying PDF, so extracting a table of transactions accurately requires understanding statement layout as a category, not just running generic text extraction over the page.

Bookkeeping reconciliation

An accountant uploads a client's monthly PDF statement and matches the extracted transactions against recorded entries in minutes.

Personal finance import

A budgeting app lets a user upload a statement from any bank and builds a transaction history without a live bank connection.

Loan underwriting

A lender extracts cash-flow patterns from applicant-submitted bank statements as part of an automated underwriting check.

Audit sampling

An auditor pulls structured transaction data from historical statements to sample and verify against internal records.

How does the Bank Statement Parser API work?

Send the statement file to POST /ocr/bank-statement, receive a task_id right away, and get the transaction list by webhook or a signed link once parsing finishes.

Is it free to test?

There's no free tier — free tiers get abused and slow everyone down. Access runs on a prepaid ForHosting KIT balance: top up from $10.00 (it never expires) and each request is charged at its published price, so a call with no balance returns HTTP 402. No subscription, no tokens, no invented credits, and a failed task is never charged.

How much does it cost?

$0.010 per request plus $0.0575 per page, published and flat, so a longer statement costs proportionally more.

Does it work with any bank's statement format?

Yes, it's built to read statement layouts generally rather than a fixed template per bank, so it adapts across formats without per-bank configuration.

What transaction fields does it return?

Date, description, amount and running balance where the statement shows one, along with account details and the statement period.

Can it handle a scanned paper statement, not just a PDF export?

Yes, clear scans work as well as digital PDF exports; a legible source page gives the most complete extraction.

Is my financial data kept?

No. Data is deleted after the retention period and is never used for training; results are delivered by signed webhook or a link valid 24 hours.

Am I billed if parsing fails?

No. A failed task is retried automatically up to three times and never charged; you get a clear error instead.

Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.

POSThttps://api.kit.forhosting.com/ocr/bank-statement

Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.

curl -X POST https://api.kit.forhosting.com/ocr/bank-statement \
  -H "Authorization: Bearer $KIT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":"…"}'
{
  "input": "…"
}
{
  "task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
  "type": "ocr.bank_statement",
  "status": "queued",
  "_links": {
    "result": "/tasks/tsk_…/result"
  }
}

The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.

Per request$0.010
Per page$0.0575

Published price — no tokens, no invented credits. A failed task is never charged.

max_mb25
max_pages10
HTTPCodeMeaning
401unauthorizedMissing or invalid API key.
402insufficient_balanceYour balance doesn't cover the task price.
404unknown_typeThat task type doesn't exist.
429rate_limitedToo many requests. Use the webhook instead of polling.
413input_too_largeThe file exceeds the size limit.
422task_failedThe task failed after 3 retries. You are never charged for it.

Read the full KIT documentation →