DEV Community

Huzaifa Zahoor
Huzaifa Zahoor

Posted on

Scripting Your Kraken Tax Exports: Proceeds, Missing Basis, and a Python Sanity Check

Every tax season, someone who writes code for a living opens a folder of exchange exports and thinks, "I'll just script this." That is a good instinct, as long as you know what each file actually means before you start summing columns. Kraken is a useful case study because it hands you several different documents, and they do not all answer the same question.

This post covers the data side: which Kraken files exist, what the IRS receives versus what only you see, and a small Python sanity check you can run on your exports. For the click-by-click download steps, Canada notes, and FAQ, see NutshellCrypto's Kraken tax report guide to the Tax Center, 1099-DA, and CSV exports.

Two places to look, and both are web-only

Kraken splits tax data across two areas, and per Kraken Support neither is available in the mobile apps:

  • Tax Center (profile icon, then Settings, then Tax Center): IRS forms plus three CSV reports for the selected year.
  • Document Center (profile icon, then Documents): raw exports such as ledger, trades, balances, and account statements.

The Tax Center CSVs are summaries. The Document Center files are closer to raw events. If your goal is reproducible numbers, keep both, because large exports can take a while to generate and Kraken says finished exports stay downloadable for only about 14 days. Save local copies the day you get them.

Know what each CSV is for

The Tax Center gives you three reports:

  1. Income Report: staking rewards, airdrops, referral bonuses, and similar earnings.
  2. Gain/Loss Report: realized disposals with proceeds, cost basis, and short- or long-term splits.
  3. Transaction History Report: everything for the year, which is the file you want for reconciliation or importing into tax software.

Treat the Gain/Loss Report as a worksheet, not a final answer. Its math depends on the lot method and on whether Kraken actually knows your cost basis.

Proceeds are not profit

This is the part that trips up anyone who "just sums the 1099." For tax year 2025, Kraken reports gross proceeds to the IRS on Form 1099-DA. The cost basis and gain figures on your copy are calculated with FIFO for convenience and were not reported to the IRS for that year. Kraken says that starting with tax year 2026 it will also report basis, acquisition date, and gain or loss for positions acquired on or after January 1, 2026.

So the number on the form is a sales total, not your taxable gain. Your gain is proceeds minus basis, and basis is the field most likely to be wrong or missing.

Missing basis is not zero basis

If you moved coins into Kraken from another wallet or exchange, Kraken often cannot see what you paid. Those rows show blank or unknown basis. Kraken's own FAQ is explicit that missing basis does not mean $0, and treating it as zero overstates your tax. A move between your own wallets is usually not a sale either, which NutshellCrypto covers in its guide to whether transferring crypto is taxable.

A quick sanity check in Python

Here is a small script that flags the two most common data problems before you import anything: disposals with no basis, and trades close enough to midnight on New Year's Eve that a UTC timestamp could push them into a different tax year. Column names differ between export versions, so open your file first and edit the three constants to match its header row.

import csv
import sys
from datetime import datetime, timezone

# Edit these to match the header row of YOUR export.
DATE_COL = "date"
PROCEEDS_COL = "proceeds"
BASIS_COL = "cost_basis"

def parse_time(value):
    dt = datetime.fromisoformat(value.replace("Z", "+00:00"))
    return dt if dt.tzinfo else dt.replace(tzinfo=timezone.utc)

def check(path):
    total, missing, edge = 0.0, [], []
    with open(path, newline="") as f:
        for i, row in enumerate(csv.DictReader(f), start=2):
            total += float(row[PROCEEDS_COL] or 0)
            if not (row.get(BASIS_COL) or "").strip():
                missing.append(i)
            ts = parse_time(row[DATE_COL])
            if (ts.month, ts.day) in ((12, 31), (1, 1)):
                edge.append((i, ts.isoformat()))
    print(f"Total proceeds: {total:,.2f}")
    print(f"Rows with blank basis (fill in, don't assume 0): {missing or 'none'}")
    print(f"Dec 31 / Jan 1 UTC rows to double-check: {edge or 'none'}")

if __name__ == "__main__":
    check(sys.argv[1])
Enter fullscreen mode Exit fullscreen mode

Run it with python check_kraken.py gain_loss_2025.csv. If the total proceeds roughly line up with the 1099-DA, your export is complete. If they don't, pull ledger history from the Document Center before going further.

What the exchange files won't cover

Kraken notes that Kraken Wallet and other DeFi activity are outside the first wave of exchange 1099-DA reporting, and that a 1099-MISC only appears for rewards of $600 or more. Small rewards are still income. If you also use other platforms, keep each one's CSVs separate and label transfers so your software doesn't count a move as a sale.

Takeaways

  • Download from the web, and save Document Center exports before they expire.
  • For 2025, the 1099-DA shows gross proceeds, not your gain.
  • Blank basis means "unknown," never zero.
  • Watch for UTC date shifts around December 31.
  • Rewards under $600 and DeFi activity still need your own records.

Read the full guide on NutshellCrypto

This is for education only and is not financial, tax, or investment advice. Talk to a qualified tax professional about your situation.

This post was written with AI assistance.

Top comments (0)