Free toolRuns in your browser

Crypto Tax CSV Validator

Before you import a year of transactions into a tax tool, check the CSV for the errors that quietly break it — malformed rows, duplicate or missing transaction ids, timezone-ambiguous timestamps, impossible amounts, unknown transaction types and balances that will not reconcile. Everything runs on your device. This is a data-quality check, not tax advice.

Your file is validated in your browser. It is never uploaded, stored or logged. Nothing happens until you pick a file.

Your file never leaves your device

Read this first

This is a data-quality tool, not tax software. It does not calculate gains, losses, cost basis or any tax figure, and it is not tax, accounting or legal advice.

A clean result means the file is internally consistent and well-formed — it does not mean your records are complete or correct, and it is not a substitute for a qualified tax professional.

We do not claim compatibility with any specific tax software. We validate a documented canonical schema plus a few exchange exports we ship a sample for; always check the output against your own provider and filing tool.

A clean result is not a guarantee that Koinly, CoinTracker, CoinLedger or any other tool will accept or correctly import your file. Each product has its own template, row limits and rules; always check the output against your own provider.

How it works

  1. Parse in the browser. Your file is parsed with a strict RFC-4180 reader that handles quoted commas, quoted line breaks, escaped quotes and a UTF-8 byte-order mark. An unterminated quote or an unreadable file is reported rather than silently mangled.
  2. Detect the format. We match the header against a documented canonical schema and a small set of exchange exports we ship a verified sample for. An unrecognised header is reported as unrecognised — we never guess what a column means.
  3. Check every row. Each row is checked for a missing or duplicate transaction id, exact-duplicate rows, non-ISO or timezone-less timestamps, impossible amounts and fees, a missing asset, an unknown transaction type, inconsistent buy/sell/trade fields, and spreadsheet-formula injection.
  4. Reconcile the totals. We replay the file per asset to find balances that cannot be reconciled — where more of an asset is disposed of than was ever acquired — and flag probable internal transfers between your own accounts that could otherwise be double-counted.
  5. Explain and normalise. You get a transparent report with a severity, the exact row numbers, a plain-language explanation and a suggested correction. When you choose to, you can download a normalised canonical CSV with formula-injection cells neutralised — your original data is preserved.

What we check

Exactly the data-quality problems the browser tool tests for — nothing more is claimed. Duplicate detection is exact-match only; it does not do fuzzy, hash-based or API-vs-CSV overlap matching.

Why these checks matter — from the official docs

Seeing a “missing purchase history”, duplicate or timezone warning after import? Read the missing-cost-basis troubleshooting guide →

What we support

A documented canonical schema first, plus exchange exports whose columns we verify against an included sample. We do not claim universal tax-software compatibility.

Canonical columns

ColumnRequiredMeaning
transaction_idrequiredUnique id for the row. Must be present and unique across the file.
timestamprequiredISO-8601 datetime WITH a timezone, e.g. 2026-01-15T14:30:00Z or 2026-01-15T09:30:00-05:00.
typerequiredOne of the canonical transaction types (buy, sell, trade, deposit, withdrawal, transfer_in, transfer_out, reward, income, fee, staking, airdrop).
assetrequiredTicker of the primary asset moved, e.g. BTC.
amountrequiredPositive quantity of `asset`. Direction comes from `type`, not a sign.
priceoptionalUnit price of `asset` in `quote_currency` at the time of a buy/sell.
quote_currencyoptionalCurrency the price is denominated in, e.g. USD.
feeoptionalPositive fee amount, if any.
fee_currencyoptionalTicker the fee was paid in.
counter_assetoptionalFor a crypto-to-crypto trade, the asset received.
counter_amountoptionalFor a trade, the positive quantity of counter_asset.
accountoptionalWallet or account label — used to pair internal transfers.
notesoptionalFree-text note. Never used in reconciliation.

Canonical transaction types: buy, sell, trade, deposit, withdrawal, transfer_in, transfer_out, reward, income, fee, staking, airdrop. Amounts are positive quantities — direction comes from the type, never a negative sign. Timestamps are ISO-8601 with an explicit timezone.

How this tool is funded

Crypto Market Lens is free. We may one day show a clearly-labelled link to a relevant, independently-approved tax tool; if we do, it will be disclosed and will never change what this validator reports. Right now this surface shows no offer at all — that is by design. Affiliate disclosure & methodology →

Questions people ask

Does this file my taxes or calculate what I owe?

No. It does not calculate gains, losses or any tax figure, and it is not tax advice. It only checks whether your transaction CSV is well-formed and internally consistent, so an import into your own tax tool does not fail or silently mis-count.

Is my file uploaded anywhere?

No. The file is read and validated entirely in your browser using a local file reader. It is never uploaded, stored or logged. We record only that a validation happened and coarse issue buckets — never a value, filename or address from your file.

Which formats do you support?

A documented canonical schema first, plus a small set of exchange exports we ship a verified sample for. We do not claim universal tax-software compatibility. If your header is not recognised, download the canonical template, map your columns onto it, and re-run.

What does a clean result actually mean?

That the file parses, every row is well-formed, and the totals reconcile. It does not mean your records are complete or your taxes are correct — missing transactions cannot be detected from a file that does not contain them. Treat it as a data check, not a clearance.

Why does it warn about timestamps without a timezone?

A timestamp with no timezone is ambiguous — the same wall-clock time is a different moment in different zones, and near a year boundary that can move a transaction into a different tax year. We read such times as UTC and flag them so you can add an explicit timezone.

What is CSV formula injection and why flag it?

A cell starting with =, +, - or @ can be executed as a formula when the file is opened in a spreadsheet, which is a known attack vector. We flag any such cell and, in the normalised download, neutralise it with a leading apostrophe so it is treated as text.