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 for one year or less, then sold | Profit is a taxable event β tax is due once the exemption threshold is reached |
| BTC held for more than one year, then sold | Profit tax-free |
| Transfer between your own wallets/accounts | The transferred holdings: not a taxable event |
| Network/withdrawal fee paid in bitcoin | Disposal of the fee portion at the daily rate (BMF circular of 6 March 2025, paras. 54, 60) β usually cents, the tool includes them |
| Bitcoin given away or donated | Not a disposal, but the coins leave your holdings β acquisition date and cost carry over to the recipient (Sec. 23 (1) sentence 3 EStG) |
| 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 August 2026: Fees Paid in Bitcoin and Gifts Are Now Included
Until now the tool treated transfers between your own wallets as tax-neutral, full stop. That is true for the transferred holdings β but not for the network fee you pay in bitcoin along the way. You hand it over in exchange for a service, and under the logic of the German Federal Ministry of Finance circular of 6 March 2025 (paras. 33, 54, 60) that is a small disposal of the fee portion. The tool now books it β which also means the reported holdings finally match your wallet.
- Fees in BTC: miner fees on BitBox sends (including wallet-internal ones), 21bitcoin withdrawal fees, Bisq trading fees β each is matched to a lot via FiFo, valued at the daily closing price and listed with gain/loss in the report (section "GEBΓHREN IN BITCOIN"). The gain counts towards the exemption threshold. In practice this amounts to cents to a few euros per year.
- Prices offline: the daily closing prices (Bitstamp BTC/EUR since 2017) ship as a table inside the tool. No price service is queried β your transaction data still never leaves the browser, and a report generated tomorrow is identical to one generated today.
- Gifts and donations: put a word like "Spende", "Geschenk", "donation" or "gift" into the transaction note in the BitBox app. The tool then books it as a gratuitous transfer: no disposal, no gain β but the coins leave your holdings, and the report shows purchase date and cost basis per lot, because both carry over to the recipient (Sec. 23 (1) sentence 3 EStG).
- Transparency: the tax evidence document explains the method itself, citing the paragraph numbers. Anyone who prefers a different treatment of the fees can see exactly which lines are affected.
Why no tax-advisor opinion on this? Because there is no explicit administrative statement and no court ruling β only the logic of the BMF circular and the practice of the major crypto tax tools, which do the same. The tool picks the traceable, documented method and lays it open. This is not tax advice.
β‘ 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