How to Import a Bank Statement Into Xero Without a Bank Feed
Xero is built around the assumption that every bank account has a live feed quietly pulling transactions in overnight. Most of the time that’s true. Then you hit an account it doesn’t have: a foreign bank with no feed partner, a credit union that dropped off Xero’s supported list, a closed account you still need historical data from, or a feed that’s been “connecting” for six days and clearly isn’t going to. When that happens, the only path forward is a manual statement import, and Xero is considerably less forgiving about the file format than QuickBooks is.
What Xero’s statement import actually wants
Xero’s manual bank statement import (under the account’s own Reconcile → Import a Statement option) expects a CSV with a specific structure: a Date column, a single Amount column with one sign convention for money in and money out, and payee/description columns. Two things trip people up almost every time:
One amount column, not two. If your source data — or your intermediate spreadsheet — has separate Debit and Credit columns, Xero’s importer doesn’t reconcile them into one column for you. You need a single signed number per row: negative for money leaving the account, positive for money coming in. Bank statements that print debits and credits as separate columns, or that suffix amounts with DR/CR instead of using a sign, need that resolved before the file goes anywhere near Xero.
Date format has to match your organisation’s regional setting. Xero reads dates according to the format configured for your organisation (commonly DD/MM/YYYY for UK/AU/NZ orgs, MM/DD/YYYY for US orgs). A file with the wrong convention doesn’t necessarily error — it can silently import 03/04/2026 as March 4th when you meant April 3rd, and you won’t notice until a transaction reconciles to the wrong period. This is the single most common invisible failure in Xero imports, because the file “worked” — it just worked wrong.
Getting there from a PDF
Start with the actual PDF, downloaded from the bank. A statement generated by the bank’s own portal has real text underneath the numbers you see — that’s what any parser (this one included) actually reads. A photo of a paper statement or a scanned image has no such layer, so there’s nothing to extract; that’s an OCR problem, not a conversion one.
Convert it with attention to the amount column, since that’s where Xero import failures actually come from. StatementKit reads the position of every piece of text pdf.js pulls off the page and works out column boundaries from where whitespace consistently lines up down the page — which is how it handles a debit/credit split or a DR/CR suffix format without needing to be told in advance that’s what a particular bank does. What you get out is one Date column, one Description column, and one signed Amount column, which is exactly the shape Xero’s importer wants and exactly the shape that’s tedious to build by hand in Excel from a two-column debit/credit layout.
Check the balance before you trust the file. Enter the statement’s printed opening and closing balance, and the tool runs every transaction forward from the opening figure, flagging the exact row where the running total stops matching what’s expected. This matters more for a Xero import than it might seem: Xero’s reconciliation screen will happily let you match transactions against a bank statement balance that’s subtly wrong because one row was misread, and you won’t find out until the reconciliation report doesn’t tie out weeks later. Catching it before export is much cheaper than catching it during a review.
Export with the Xero-formatted CSV. Rather than reshaping a generic export by hand, the dedicated Xero export writes Date, Amount, Payee, Description — the layout documented for Xero’s statement import — with one signed amount column and dates formatted the way you’ve set in the export options (match this to your organisation’s regional date setting, since that’s the one field Xero won’t sanity-check for you).
Importing and reconciling in Xero
In Xero, go to the bank account’s Reconcile tab, choose Import a Statement, and upload the CSV. Xero will show you a preview of the parsed rows before committing — this is your last checkpoint, and it’s worth actually reading a few rows rather than clicking through, specifically checking that dates landed in the month you expect and that amounts have the sign you expect. Once imported, the transactions sit in the “Reconcile” queue the same way feed-imported transactions do, ready to match against invoices, bills, or existing ledger entries.
One quirk specific to manual imports: Xero doesn’t automatically detect duplicates against a feed the way it does for connected accounts, so if you’re re-importing a statement that overlaps a period you already entered manually, you’re relying on your own diligence (or Xero’s built-in duplicate-detection prompt during import, which catches identical date+amount+reference combinations but not near-duplicates with slightly different descriptions).
Why this comes up more for certain clients
If you do books for clients with international suppliers, foreign currency accounts, or newer fintech banking products, you’ll hit the “no feed available” wall more often than you’d expect — Xero’s feed coverage is good but not universal, and it changes without much warning when a feed partner relationship ends. Building a reliable manual-import habit isn’t a workaround for an edge case; for some client rosters, it’s the default path for at least one account every month.
The PDF and the CSV you export both stay on your device the whole time — StatementKit doesn’t have a server to send them to, so there’s nothing to worry about handing a client’s statement to a third party in the process.
Working with Discover statements specifically? See converting a Discover statement to Excel.