Simple ingesting tools for Beancount (plain text, double entry accounting software). More importantly, a framework to allow you to easily write your own importers.
Python
166
554 commits
updated Apr 30, 2026
beancount_reds_importers is being transitioned from Beancount v2 to Beangulp (Beancount v3's importer framework). The Beangulp version is not yet ready for release. So:
pip3 install beancount-reds-importerspip3 install git+https://github.com/redstreet/beancount_reds_importers), but be warned that you'll
run into breakages (please file bug reports!)Simple importers and tools for Beancount, software for plain text, double entry bookkeeping. More importantly, a framework to allow you to easily write your own importers.
This is a reference implementation of the principles expressed in The Five Minute Ledger Update.
Importers can be ugly and painful to write, yet are important in automating the grunt work out of maintaining personal finance software. The philosophy is to make writing sustainable, dependable importers easy. To achieve this, the design separates importers in to three parts:
This design helps move most of the heavy-lifting common code into (1) and (2) above. Writing new importers is made easier since one only has to write code to address the institution-specific formatting and quirks for each bank/brokerage. See working examples of an ofx based and csv based importers.
File format readers included are:
.ofx.csv (single and multitable support).xlsx (single and multitable support) (pip3 install xlrd if you plan to use this).pdf (single and multitable support)Transaction builders included are:
Input in .ofx format (over .csv) is preferred,
when provided by the institution, as it minimizes data and coding errors, eliminates
format breaking changes in .csv files, and typically includes balances that are used to
generate balance assertions, and commodity prices.
See here for a list of institutions built-in. More investment, credit card, and banking institutions will be added in the future. Contributions welcome.
These commands are installed as a part of the pip installation:
ofx-summarize: Quick and dirty way to summarize a .ofx file, and peek inside itbean-download: Download account statements automatically
(for supporting institutions), from your configuration of accounts. Multi-threaded.
bean-download needs-update is a configurable utility that shows you the last time
each account was updated, based on the latest balance assertion in your journal. See
this article
for more.The commands include shell auto-completion (tab-to-complete) via
click. bean-download, in
particular, can complete the account or account groups you want to download, which can
be handy. To enable it in zsh, do
(see here for other shells):
mkdir -p ~/.zcomplete
_OFX_SUMMARIZE_COMPLETE=zsh_source ofx-summarize > ~/.zcomplete/ofx-summarize-complete.zsh
_BEAN_DOWNLOAD_COMPLETE=zsh_source bean-download > ~/.zcomplete/bean-download-complete.zsh
# Place this in your shell's rc file (.zshrc or .bashrc or .fishrc):
for f in ~/.zcomplete/*; do source $f; done
bean-extract
ofxclient, connecting to smart_importer to
auto-classify transactions, and morepip3 install beancount-reds-importers
Or to install the bleeding edge version from git (which I recommend, as long as you are willing to understand there might be a bug or two):
pip3 install git+https://github.com/redstreet/beancount_reds_importers
cd <your pip installed dir>/example #eg: cd ~/.local/lib/python3.8/site-packages/beancount_reds_importers/example./import.sh OfxDownload.qfx # Imports investments./import.sh transactions.qfx # Import bank transactions; uses smart_importer to classify transactions_config.py and _config-smart.py files provided. At the least, include your account numbersfund_info.py to start with.my_config.py identify, my_config.py extract, etc. See the included script: Run ./import.sh <your_input_ofx>fund_info.py See
this article
for automating and managing identifier infoChoices for the date of the generated balance assertion can be specified as a key in
the importer config, balance_assertion_date_type, which can be set to:
smart: smart date (default; see below)ofx_date: date specified in ofx filelast_transaction: latest transaction date (the "tightest" assertion)today: today's dateIf you need something else, simply override this method in individual importer.
smart dates: Banks and credit cards typically have pending transactions that are not
included in downloads. When we download the next statement, new transactions may appear
prior to the balance assertion date that we generate for this statement, which renders
this balance assertion invalid. This problem manifests occasionally as an existing
balance statement breaking when a new statement is downloaded and is an annoyance as it
needs manual fixing.
To minimize this, we set the balance assertion date to either two days (fudge factor to
account for pending transactions) before the statement's end date or the last
transaction's date, whichever is later. To choose a different fudge factor, simply set
balance_assertion_date_fudge in your config.
For Excel files (.xls/.xlsx), currency amounts are quantized to 2 decimal places by
default. Note that .xlsx files will honor Excel cell number formats when available,
falling back to the default precision otherwise. For currencies requiring different
precision (e.g., JPY with 0 decimals, or cryptocurrencies with 8 decimals), set
currency_precision in your importer's custom_init():
def custom_init(self):
self.currency_precision = 0 # For JPY
# or self.currency_precision = 8 # For cryptocurrencies
Depending on the institution, the payee and narration fields in generated
transactions may appear to be switched. This is described by
libtransactionbuilder/banking.py,
and the fields can be swapped in a custom_init.
pip3 install xlrd
uv run pytest
Some importers are tested with
regression_pytest.py.
Run pytest --generate then pytest.
Anonymized data to increase regression test coverage is most welcome. Please submit a PR if you can. See here for an example to follow.
More broadly I run tests across hundreds of actual ofx and csv files, against reference outputs that I know to be correct from my personal file. However, I'm unable to share them since these are personal. Testing against real world files is best, so I recommend you do this with your own input files.
Feel free to post questions/concerns in the Beancount groups or on The Five Minute Ledger Update site. For bugs, open an issue here on Github.
Features, fixes, and improvements welcome. New importers for institutions with test input files appreciated. Sharing importers helps the community! Remember:
Thank you for contributing!
Python
99.7%
Simple ingesting tools for Beancount (plain text, double entry accounting software). More importantly, a framework to allow you to easily write your own importers.
Python
166
554 commits
updated Apr 30, 2026
beancount_reds_importers is being transitioned from Beancount v2 to Beangulp (Beancount v3's importer framework). The Beangulp version is not yet ready for release. So:
pip3 install beancount-reds-importerspip3 install git+https://github.com/redstreet/beancount_reds_importers), but be warned that you'll
run into breakages (please file bug reports!)Simple importers and tools for Beancount, software for plain text, double entry bookkeeping. More importantly, a framework to allow you to easily write your own importers.
This is a reference implementation of the principles expressed in The Five Minute Ledger Update.
Importers can be ugly and painful to write, yet are important in automating the grunt work out of maintaining personal finance software. The philosophy is to make writing sustainable, dependable importers easy. To achieve this, the design separates importers in to three parts:
This design helps move most of the heavy-lifting common code into (1) and (2) above. Writing new importers is made easier since one only has to write code to address the institution-specific formatting and quirks for each bank/brokerage. See working examples of an ofx based and csv based importers.
File format readers included are:
.ofx.csv (single and multitable support).xlsx (single and multitable support) (pip3 install xlrd if you plan to use this).pdf (single and multitable support)Transaction builders included are:
Input in .ofx format (over .csv) is preferred,
when provided by the institution, as it minimizes data and coding errors, eliminates
format breaking changes in .csv files, and typically includes balances that are used to
generate balance assertions, and commodity prices.
See here for a list of institutions built-in. More investment, credit card, and banking institutions will be added in the future. Contributions welcome.
These commands are installed as a part of the pip installation:
ofx-summarize: Quick and dirty way to summarize a .ofx file, and peek inside itbean-download: Download account statements automatically
(for supporting institutions), from your configuration of accounts. Multi-threaded.
bean-download needs-update is a configurable utility that shows you the last time
each account was updated, based on the latest balance assertion in your journal. See
this article
for more.The commands include shell auto-completion (tab-to-complete) via
click. bean-download, in
particular, can complete the account or account groups you want to download, which can
be handy. To enable it in zsh, do
(see here for other shells):
mkdir -p ~/.zcomplete
_OFX_SUMMARIZE_COMPLETE=zsh_source ofx-summarize > ~/.zcomplete/ofx-summarize-complete.zsh
_BEAN_DOWNLOAD_COMPLETE=zsh_source bean-download > ~/.zcomplete/bean-download-complete.zsh
# Place this in your shell's rc file (.zshrc or .bashrc or .fishrc):
for f in ~/.zcomplete/*; do source $f; done
bean-extract
ofxclient, connecting to smart_importer to
auto-classify transactions, and morepip3 install beancount-reds-importers
Or to install the bleeding edge version from git (which I recommend, as long as you are willing to understand there might be a bug or two):
pip3 install git+https://github.com/redstreet/beancount_reds_importers
cd <your pip installed dir>/example #eg: cd ~/.local/lib/python3.8/site-packages/beancount_reds_importers/example./import.sh OfxDownload.qfx # Imports investments./import.sh transactions.qfx # Import bank transactions; uses smart_importer to classify transactions_config.py and _config-smart.py files provided. At the least, include your account numbersfund_info.py to start with.my_config.py identify, my_config.py extract, etc. See the included script: Run ./import.sh <your_input_ofx>fund_info.py See
this article
for automating and managing identifier infoChoices for the date of the generated balance assertion can be specified as a key in
the importer config, balance_assertion_date_type, which can be set to:
smart: smart date (default; see below)ofx_date: date specified in ofx filelast_transaction: latest transaction date (the "tightest" assertion)today: today's dateIf you need something else, simply override this method in individual importer.
smart dates: Banks and credit cards typically have pending transactions that are not
included in downloads. When we download the next statement, new transactions may appear
prior to the balance assertion date that we generate for this statement, which renders
this balance assertion invalid. This problem manifests occasionally as an existing
balance statement breaking when a new statement is downloaded and is an annoyance as it
needs manual fixing.
To minimize this, we set the balance assertion date to either two days (fudge factor to
account for pending transactions) before the statement's end date or the last
transaction's date, whichever is later. To choose a different fudge factor, simply set
balance_assertion_date_fudge in your config.
For Excel files (.xls/.xlsx), currency amounts are quantized to 2 decimal places by
default. Note that .xlsx files will honor Excel cell number formats when available,
falling back to the default precision otherwise. For currencies requiring different
precision (e.g., JPY with 0 decimals, or cryptocurrencies with 8 decimals), set
currency_precision in your importer's custom_init():
def custom_init(self):
self.currency_precision = 0 # For JPY
# or self.currency_precision = 8 # For cryptocurrencies
Depending on the institution, the payee and narration fields in generated
transactions may appear to be switched. This is described by
libtransactionbuilder/banking.py,
and the fields can be swapped in a custom_init.
pip3 install xlrd
uv run pytest
Some importers are tested with
regression_pytest.py.
Run pytest --generate then pytest.
Anonymized data to increase regression test coverage is most welcome. Please submit a PR if you can. See here for an example to follow.
More broadly I run tests across hundreds of actual ofx and csv files, against reference outputs that I know to be correct from my personal file. However, I'm unable to share them since these are personal. Testing against real world files is best, so I recommend you do this with your own input files.
Feel free to post questions/concerns in the Beancount groups or on The Five Minute Ledger Update site. For bugs, open an issue here on Github.
Features, fixes, and improvements welcome. New importers for institutions with test input files appreciated. Sharing importers helps the community! Remember:
Thank you for contributing!
Python
99.7%