CSV to Beancount Converter

Convert any CSV bank statement or transaction export to Beancount double-entry ledger format. Interactive column mapping, configurable accounts, runs in your browser.

1.0.0
Version
Auth
Batch

About CSV to Beancount Converter

You're a Beancount user with a stack of bank CSVs — Chase, Wise, Revolut, Monzo, N26, 招商银行, whatever the bank handed over — and you want them in your .bean ledger before tonight's bean-check pass. The official path is to install Python, pip-install beancount plus a per-bank importer, write a config file, learn the importer's class hierarchy, and only then turn one CSV into a ledger. For a one-off conversion, that's a workshop's worth of setup before you even open the file.

This CSV to Beancount converter skips the toolchain. Drop a CSV onto the page, the parser auto-detects delimiter (, ; \t |) and encoding (UTF-8, GBK, GB18030, Latin-1 — so Chinese bank exports work without re-saving), then suggests sensible column mappings by matching English and Chinese header keywords (amount, date, 金额, 交易时间, 对方). You map five fields — Date, Amount, Payee, Description, Category — pick a date format if auto guesses wrong, optionally flip the sign for CSVs where expenses are shown positive, then name the source/expense/income accounts and a currency. Out comes a sorted Beancount ledger with open directives, ready to drop in.

Useful for migrating a year of statements into a fresh ledger, building a one-time import while your real automation is still half-built, filling a gap when a bank-specific importer is broken, or simply staying private — bank transactions are sensitive and never leave your browser here. Output stats show entry count, debit/credit totals and date range so you can sanity-check before committing.

CSV to Beancount Converter Use Cases

  • New Beancount users migrating a year of bank statements before adopting fava
  • Existing ledger keepers handling a CSV from a bank with no Python importer
  • Migrating from YNAB, Mint or Excel to plain-text double-entry accounting
  • Importing Chinese bank exports (招商, 工商, 支付宝) where encoding is GBK
  • Filling a gap month when an automated importer broke or skipped transactions
  • Privacy-minded users who refuse to upload statements to a SaaS converter
  • Quick one-off conversions during travel without a Python environment handy

CSV to Beancount Converter Features

  • CSV parsed and converted entirely in your browser — no upload, no signup, bank statements never leave the page
  • Auto-detects delimiter (comma, semicolon, tab, pipe) and encoding (UTF-8, GBK, GB18030, Latin-1) for international banks
  • Smart column auto-mapping for English and Chinese headers — date, amount, payee, 日期, 金额, 对方, 商户, 备注
  • Date format auto-detect plus manual override for YYYY-MM-DD, DD/MM/YYYY, MM/DD/YYYY, DD.MM.YYYY, YYYY/MM/DD
  • Sign-inversion toggle handles both bank-style (negative for expenses) and expense-positive CSVs
  • Generates open directives at the earliest date plus sorted transactions with payee, narration and account splits
  • Output stats show entry count, total debits, total credits, date range and skipped rows for sanity-checking

How to Use CSV to Beancount Converter

Upload your CSV

Drag a bank or card CSV onto the upload zone (Chase, Wise, Revolut, Monzo, N26 and most Chinese banks all work). The parser detects delimiter and encoding automatically, but you can override either if your file is unusual.

Map columns to Beancount fields

Five dropdowns appear — Date, Amount, Payee, Description, Category. Headers matching common keywords (English and Chinese) are pre-selected. The highlighted columns in the preview table show what the importer will actually use.

Pick date format and sign

If the auto date format guesses wrong (DD/MM/YYYY vs MM/DD/YYYY is the classic trap), pick the right one. Tick 'Invert sign' if your CSV shows expenses as positive numbers rather than the bank-standard negative.

Name your accounts

Set the source account (Assets:Bank:Checking by default), default expense and income accounts (Expenses:Unknown, Income:Unknown), the currency (USD default) and an optional narration prefix like 'Chase checking'.

Generate, copy or download

Click Generate Beancount. The output panel shows the ledger with entry count, debit/credit totals and date range. Copy the text or download as a .bean file ready to drop into your ledger and run bean-check or fava.

CSV to Beancount Converter FAQ

No. The CSV is parsed and converted entirely in client-side JavaScript — file bytes are read with FileReader, decoded in-memory, and the resulting Beancount text is generated as a string in the page. There is no upload, no fetch, no analytics call. Bank transactions are sensitive enough that this is the only reasonable default. Open DevTools, switch to Network, generate and verify nothing fires.

Any bank or card that exports CSV. Confirmed working with Chase, Bank of America, Wells Fargo, Wise, Revolut, Monzo, N26, Deutsche Bank, ING, 招商银行, 工商银行 and 支付宝 transaction exports. Because column mapping is interactive rather than hard-coded per bank, any reasonable CSV layout works as long as you have a date column and an amount column.

Two conventions exist for amount columns. Most bank CSVs are signed (an expense is -45.67 and a deposit is +1200.00). Some exports — especially expense-tracker apps — show everything as positive numbers and use a separate debit/credit column instead. Tick Invert sign when your CSV shows expenses as positive, so debit transactions land on the Expenses account in the ledger.

beancount-import is a Python web UI that needs a local install, per-bank importer classes and a long-lived ledger with categorisation history. beanhub is a hosted service with an account. This is a stateless converter that runs in the browser — best for one-off imports, migrations, or any case where you don't want to install Python or hand statements to a third party. Use it to bootstrap your ledger, then graduate to a real importer for ongoing flow.

Bytes are decoded with TextDecoder in strict mode, starting with UTF-8. If UTF-8 fails, it falls back to GBK then GB18030 — the standard encodings for Chinese bank exports — and finally to Latin-1 as a permissive last resort. Manual override is available if your file is something unusual like Shift-JIS. The encoding choice changes the parsing stage, so flipping it re-parses the file in place.

A header comment block with the source filename, generation time and date range. Then open directives at the earliest transaction date for the three accounts and currency. Then transactions sorted ascending by date in standard Beancount syntax — date marker, * flag, payee, narration, source account with signed amount and currency, target Expense or Income account on a second posting. bean-check accepts the output directly.

All expenses default to Expenses:Unknown and all income to Income:Unknown. The converter does not attempt to auto-categorise — categorisation rules are the job of a real importer with a learned ruleset. The intent here is to get you a syntactically valid, dated, balanced ledger quickly so you can run sed, fava's account-rewrite, or manual edits to refine categories afterwards.

Zero uploads. CSV parsing and conversion happen entirely in your browser.

1Upload CSV

Upload CSV or drag here

Bank statement, credit card export, expense tracker dump…

CSV to Beancount Converter Tutorial

What is Beancount?

Beancount is a plain-text, double-entry accounting system. Every transaction has two entries that must balance — money doesn't just appear or vanish, it moves from one account to another. It's the geekiest, most auditable way to do personal or small-business finance.

2026-04-01 * "Trader Joe's" "Groceries"
  Assets:Bank:Checking  -45.67 USD
  Expenses:Food:Groceries

Why This Tool?

Banks export CSV. Beancount wants its own syntax. Hand-converting 500 transactions is tedious and error-prone. This tool maps your CSV columns to Beancount fields and spits out a ready-to-bean-check ledger.

Workflow

  1. Upload your bank's CSV export
  2. Pick which columns are Date, Amount, Payee, Description
  3. Tick "Invert sign" if your CSV has 45.67 for expenses (bank CSVs are usually signed already with negative for debits)
  4. Set account names — the source account (your bank) and the default expense/income accounts
  5. Download the .bean file, drop it into your ledger, run fava or bean-check

Auto-detection Features

  • Delimiter — tries ,, ;, tab, |
  • Encoding — UTF-8, GBK (for Chinese banks), GB18030, Latin-1
  • Date format — YYYY-MM-DD, DD/MM/YYYY, MM/DD/YYYY, DD.MM.YYYY

Compatible CSV Sources

Any bank that gives you a CSV. Confirmed working with: Chase, Bank of America, Wells Fargo, Wise, Revolut, Monzo, N26, Deutsche Bank, ING, 招商银行, 支付宝 (for just the raw transactions), 工商银行.