The fastest safe way to convert a bank statement PDF into structured data is text-layer extraction to Markdown: statements downloaded from your bank are digital-native PDFs, so the transaction table can be read exactly — every date, description, and amount — without OCR guessing at digits. From Markdown, CSV is one step away.
Two things matter more for bank statements than for any other document: accuracy on numbers (an OCR misread of 8 as 3 in an amount is a real problem) and privacy (a statement is about the most sensitive document you can paste into a random website).
Step 1: Convert the statement to Markdown
In the browser: drag the PDF into the free converter — no signup, and the file is processed in memory, never stored or logged.
In code: one request, no API key:
curl -s https://api.marklipi.com/convert -F "file=@statement.pdf" | jq -r .markdown > statement.md
The transaction table comes out as a Markdown table:
| Date | Description | Debit | Credit | Balance |
| ---------- | ---------------------- | ------ | ------- | -------- |
| 2026-06-01 | Opening balance | | | 4,210.55 |
| 2026-06-03 | Payroll — Dovey Labs | | 2,900.00| 7,110.55 |
| 2026-06-04 | Woolworths Sydney | 82.10 | | 7,028.45 |
Because this reads the PDF’s text layer, the numbers are the bank’s own characters — nothing recognized, nothing hallucinated. That determinism is why text extraction beats vision models for financial documents (the full argument).
Step 2: Markdown table → CSV
A Markdown table is already delimiter-separated — pipes instead of commas. Any of these gets you to CSV:
- Spreadsheet: paste the rows into Excel/Google Sheets, split on
|(Text to Columns), delete the separator row. - One-liner:
grep '^|' statement.md | sed 's/^ *| *//; s/ *| *$//; s/ *| */,/g' | grep -v '^-' > statement.csv
- LLM: for messy statements, paste the Markdown into a model and ask for normalized CSV — the Markdown version costs a fraction of the tokens the raw PDF would.
What about scanned or photographed statements?
If the statement was scanned on paper (or is a photo), there’s no text layer and this method returns a clear 422 error rather than guessed numbers. That’s deliberate — for financial data you want to know when you’re getting OCR output so you can verify it. Route scans to an OCR pipeline and double-check amounts. How to tell which kind of PDF you have.
Automating monthly statements
Processing statements for bookkeeping, an expense app, or an agent pipeline? The same conversion is an API built for automation — keyless, JSON out, 100 free conversions a day:
import requests
with open("2026-06-statement.pdf", "rb") as f:
r = requests.post("https://api.marklipi.com/convert", files={"file": f}, timeout=60)
transactions_md = r.json()["markdown"]
Full Python/Node examples are in the integration guide.
FAQ
Is it safe to upload a bank statement to a converter?
Only if the service is explicit about retention. marklipi processes files in memory and discards them when the response returns — nothing stored, nothing logged, no account attaching the file to you. Avoid converters that don’t state a retention policy.
Why not just copy-paste from the PDF?
Selecting a table in a PDF viewer usually copies it in reading order — columns interleave and alignment is lost. Table-aware extraction preserves the grid.
Can it handle statements from any bank?
Any digitally issued statement (downloaded from online banking) has a text layer and converts. Layout quality varies by bank; whitespace-aligned transaction tables are the common case and extract as proper tables.