You hold Bitcoin in self-custody. Good. You buy through multiple brokers. Even better. And now the tax authority asks which coins you bought when, which of them are tax-free and exactly how high your taxable gain is.
For exactly this problem there is the BTC Tax Tool โ an open-source CLI tool I developed myself for my own tax return. It reads your CSV exports from BitBox, 21bitcoin, Bison, Swissquote, Strike and Pocket and automatically calculates what has to go to the tax office and what remains tax-free.
"Don't Trust, Verify โ including your accountant. If you understand how the calculation works, you're not at anyone's mercy."
๐ธ NEW: The Web Version โ drop your CSVs, get your report
No Python, no terminal: the tax tool now runs as a web app. Drag your CSV exports into the browser, the app detects every broker automatically and computes all tax years at once. Your files never leave your machine โ the entire calculation runs locally in your browser via WebAssembly. No upload, no account, no tracking. Same open-source calculation engine as the CLI tool.
Note: the web app interface is currently German only (it produces reports for the German tax system, ยง 23 EStG).
โ Try the free demo (with fictional sample data)
โ The guide โ step by step with screenshots
โ Get access โ โฌ29, 30 days (Lightning, on-chain, fiat)
1. The Foundation: What German Tax Law Says
Bitcoin is classified in Germany as a private disposal transaction (ยง 23 EStG). The rules:
| Situation | Tax treatment |
|---|---|
| BTC held less than 365 days, then sold | Profit taxable |
| BTC held more than 365 days, then sold | Profit tax-free |
| Transfer between your own wallets/accounts | Not a taxable event |
| Profit under 600 EUR/year (until 2023) | Exemption threshold โ not a single cent in tax |
| Profit under 1,000 EUR/year (from 2024) | Exemption threshold โ not a single cent in tax |
The method is called FiFo โ First In, First Out. That means: what you buy first, you also sell first. Sounds simple, but gets complicated quickly when you buy from five brokers and your BTC moves between multiple wallets.
The Exemption Threshold Is a Trap
Many people think: "I'm under 1,000 EUR, so it's irrelevant." Wrong. The exemption threshold is not a tax allowance. If you exceed it, the entire taxable profit becomes taxable โ not just the part above it. A profit of 1,001 EUR is therefore fully taxable โ not just that one euro.
2. The Problem with Self-Custody
Tax apps like CoinTracking or Blockpit work well for exchanges that record everything. For genuine self-custody holders with hardware wallets, problems arise:
- You transfer BTC from your BitBox to an exchange for a sale โ this looks like a purchase.
- You have multiple wallets โ the cost basis travels with them.
- Swissquote buys in USD โ the historical exchange rate must be correctly factored in.
- You enter your complete financial data into a cloud app โ that contradicts the whole point of self-custody.
The BTC Tax Tool runs locally on your machine. No cloud, no registration, no third-party servers. Your data stays with you.
From here on: the path for technical users (free CLI tool)
Sections 3โ5 below describe the free CLI tool from GitHub โ for everyone
who likes working in a terminal.
Using the web version? Then there is nothing to
install. No Python, no download, no setup โ open your browser, drop your CSVs,
done. Skip straight to section 6: What you submit to the tax office.
3. Installing the CLI tool (one-time โ GitHub version only)
You need Python 3 โ on Linux and macOS it is already installed. On Windows you may need to install it first (python.org).
Mac / Linux:
git clone https://github.com/Alien-Investor/btc-steuertool.git cd btc-steuertool python3 -m venv .venv .venv/bin/pip install -r requirements.txt
Windows:
git clone https://github.com/Alien-Investor/btc-steuertool.git cd btc-steuertool python -m venv .venv .venv\Scripts\pip install -r requirements.txt
That's it. No database, no server, no subscription.
4. Place Your CSV Files (CLI)
Export your CSV files from the respective apps and place them in the corresponding folders.
The folders bitbox/ and Broker/ don't exist yet after cloning โ
they are listed in .gitignore so your financial data never accidentally ends up on GitHub.
You need to create them once yourself:
Mac / Linux:
mkdir -p bitbox Broker
Windows:
mkdir bitbox mkdir Broker
| Source | Folder | Filename |
|---|---|---|
| BitBox (hardware wallet) | bitbox/ |
any name, all *.csv files are loaded |
| 21bitcoin | Broker/ |
must start with 21bitcoin |
| Bison | Broker/ |
Bison-CSV-Gesamt.csv |
| Swissquote | Broker/ |
Swissquote_CSV-Gesamt.csv |
| Strike | Broker/ |
strike_2024.csv, strike_2025.csv etc. |
Broker/ |
must start with Pocket |
|
| noKYC purchases (Bisq, Robosats, P2P, cash) | Project folder | manual_buys.csv โ optional, create yourself |
| Private sales (P2P without broker) | Project folder | manual_sales.csv โ optional, create yourself |
Your data stays local
The folders bitbox/ and Broker/ as well as the files
manual_buys.csv and manual_sales.csv are listed in
.gitignore โ they will never accidentally be checked into Git
or put online. Your financial data stays on your machine.
noKYC Purchases and Private Sales
Anyone who buys BTC without a KYC broker โ via Bisq, Robosats, HodlHodl or directly person-to-person โ
has no broker CSV. For this there is manual_buys.csv: a simple text file
in the project folder where you enter each purchase with date, BTC amount and EUR amount.
date,btc_amount,eur_amount,note 2024-03-10,0.01000000,550.00,Bisq P2P purchase 2024-07-22,0.00500000,280.00,Robosats trade
Same principle for private sales without a broker: manual_sales.csv in the same format.
The tool reads both files automatically and processes them like any other purchase or sale.
On the legal situation: You are not required to disclose your complete wallet fingerprint. As long as acquisition costs are correctly stated and taxable gains are fully reported, this is unproblematic under tax law. The tax authority has no claim to your complete UTXO history.
โก Update June 2026: Bisq Direct Import + Strict noKYC Separation
The tool now supports direct import of the Bisq trade history CSV. Simply place the export from Bisq ("Portfolio โ History โ Export") as bisq.csv in the Broker/ folder โ the tool automatically recognises all completed purchases.
- Bisq direct import: No more manual entry. The parser reads price, BTC amount, EUR amount and fees directly from the Bisq export.
- Dedicated noKYC file: noKYC purchases do not appear in any tax-office document. They go into a separate file
nokyc_intern_YEAR.txtโ with a clear warning header at the top so it can never accidentally be handed in along with the official documents. - Separate FiFo pools: KYC and noKYC holdings live in two strictly separated FiFo pools. A broker sale can never be matched against a Bisq purchase as its cost basis โ the official proof document is guaranteed to stay internally consistent.
- noKYC wallets: Running a dedicated wallet just for noKYC sats? Place its CSV in the subfolder
bitbox/nokyc/โ all movements appear exclusively in the internal report. - noKYC sales:
manual_sales.csvnow has an optionalno_kyccolumn. P2P sales from your noKYC holdings are calculated internally with FiFo matching, holding period and gain โ but only ever appear in the internal file.
Also: the holding period is now calculated calendar-exact (anniversary date instead of a rigid 365-day count) โ correct across leap years too.
For Robosats, HodlHodl and other P2P purchases without a CSV export, manual_buys.csv remains the right approach โ also with noKYC separation.
Bisq is currently the only noKYC platform with a dedicated parser. The tool is MIT-licensed โ anyone wanting to contribute an importer for Robosats, HodlHodl or other platforms is very welcome.
5. Your First Report (CLI)
Output a report for a specific year:
.venv/bin/python src/main.py --year 2024
All years at once:
.venv/bin/python src/main.py --all
With formal documentation for your accountant or tax office:
.venv/bin/python src/main.py --year 2024 --csv --nachweis
The result lands in reports/: a readable tax report, a print-ready
formal proof of calculation and optionally CSV tables for Excel.
6. What You Submit to the Tax Office (Web & CLI)
The proof alone is not enough. The tax office wants to know that the purchase data is genuine. So always submit two parts:
- The tax proof โ what the tool generates (
steuernachweis_YEAR.txt). - The original broker CSVs โ as evidence that the purchases actually took place.
The tool shows in the proof under "Source" exactly which broker provided which lot โ so you can trace every single sale without gaps.
7. What This Tool Is Not
Not a replacement for a tax advisor. If you have taxable gains, have the results reviewed โ especially in the first year. The tool calculates correctly according to FiFo, but you are responsible for the accuracy of your inputs.
What it is: a tool that informs and prepares you โ instead of leaving you blindly trusting a cloud app you don't control.
Open Source on GitHub & Codeberg
The complete code is public, free and open-source. You can verify how every line of the calculation works. Fictional sample data for all supported brokers is included as well โ so you can test the tool before loading your real data.
github.com/Alien-Investor/btc-steuertool ยท ๐ codeberg.org/Alien-Investor/btc-steuertool