Gross income minus deductions (excluding this gain).
Single
Married Filing Jointly
Head of Household
Married Filing Separately
Short Term (Less than 1 year)
Long Term (More than 1 year)
Total Capital Gain:$0.00
Applicable Tax Rate:0%
Estimated Federal Tax:$0.00
Net Profit (After Tax):$0.00
Understanding Capital Gains Tax in 2024
Whether you are trading stocks, selling real estate, or liquidating cryptocurrency, understanding your capital gains tax liability is crucial for accurate financial planning. This calculator helps you estimate your potential federal tax bill based on the 2024 tax brackets and your specific filing status.
Short-Term vs. Long-Term Capital Gains
The duration you hold an asset significantly impacts your tax rate. The IRS categorizes gains into two main buckets:
Short-Term Capital Gains: Assets held for one year or less. These are taxed as ordinary income, meaning they are subject to your standard federal income tax bracket (ranging from 10% to 37%).
Long-Term Capital Gains: Assets held for more than one year. These benefit from preferential tax rates of 0%, 15%, or 20%, depending on your taxable income.
2024 Long-Term Capital Gains Tax Brackets
For the 2024 tax year (taxes filed in 2025), the income thresholds for long-term capital gains rates are as follows:
Single Filers
0% Rate: Taxable income up to $47,025
15% Rate: Taxable income between $47,026 and $518,900
20% Rate: Taxable income over $518,900
Married Filing Jointly
0% Rate: Taxable income up to $94,050
15% Rate: Taxable income between $94,051 and $583,750
20% Rate: Taxable income over $583,750
Net Investment Income Tax (NIIT)
High-income earners may be subject to an additional 3.8% Net Investment Income Tax. This applies if your Modified Adjusted Gross Income (MAGI) exceeds specific thresholds ($200,000 for single filers, $250,000 for married filing jointly). This calculator includes the base capital gains tax but remember to consult a tax professional regarding NIIT if your income is high.
Strategies to Lower Your Tax Liability
Investors often use specific strategies to manage their tax burden:
Tax-Loss Harvesting: Selling underperforming assets at a loss to offset gains realized from other assets.
Hold for Over a Year: Waiting until the 366th day to sell can significantly reduce your rate from ordinary income levels to the long-term capital gains rates.
Retirement Accounts: Trading within a 401(k) or IRA defers taxes until withdrawal (or eliminates them in the case of a Roth IRA).
Disclaimer: This calculator provides estimates for educational purposes only and does not constitute professional tax advice. Tax laws are complex and subject to change. Please consult with a CPA or tax professional for your specific situation.
function calculateCapitalGains() {
// 1. Get Input Values
var purchasePrice = parseFloat(document.getElementById("purchasePrice").value);
var salePrice = parseFloat(document.getElementById("salePrice").value);
var annualIncome = parseFloat(document.getElementById("annualIncome").value);
var filingStatus = document.getElementById("filingStatus").value;
var holdingPeriod = document.getElementById("holdingPeriod").value;
// 2. Validation
if (isNaN(purchasePrice) || isNaN(salePrice) || isNaN(annualIncome)) {
alert("Please enter valid numbers for all price and income fields.");
return;
}
// 3. Calculate Base Gain
var gain = salePrice – purchasePrice;
// Handle Loss
if (gain <= 0) {
document.getElementById("results").style.display = "block";
document.getElementById("displayTotalGain").innerHTML = formatCurrency(gain);
document.getElementById("displayTaxRate").innerHTML = "0%";
document.getElementById("displayTaxAmount").innerHTML = "$0.00";
document.getElementById("displayNetProfit").innerHTML = formatCurrency(gain); // Loss is the net result
return;
}
var taxAmount = 0;
var averageRate = 0;
// 4. Logic Switch: Short Term vs Long Term
if (holdingPeriod === "short") {
// Short Term: Taxed as Ordinary Income
// We calculate the tax on the gain by stacking it on top of annual income
var baseTax = calculateOrdinaryIncomeTax(annualIncome, filingStatus);
var totalTax = calculateOrdinaryIncomeTax(annualIncome + gain, filingStatus);
taxAmount = totalTax – baseTax;
} else {
// Long Term: Preferential Rates (0%, 15%, 20%)
// We stack the gain on top of the annual income to see which bracket it falls into
taxAmount = calculateLongTermTax(annualIncome, gain, filingStatus);
}
// 5. Calculate Metrics
averageRate = (taxAmount / gain) * 100;
var netProfit = gain – taxAmount;
// 6. Update UI
document.getElementById("results").style.display = "block";
document.getElementById("displayTotalGain").innerHTML = formatCurrency(gain);
document.getElementById("displayTaxRate").innerHTML = averageRate.toFixed(2) + "%";
document.getElementById("displayTaxAmount").innerHTML = formatCurrency(taxAmount);
document.getElementById("displayNetProfit").innerHTML = formatCurrency(netProfit);
}
// Helper: Format Currency
function formatCurrency(num) {
return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(num);
}
// Logic: Calculate Long Term Capital Gains Tax (Progressive filling)
function calculateLongTermTax(baseIncome, gainAmount, status) {
// 2024 LTCG Brackets
var brackets = {
'single': [47025, 518900],
'married_joint': [94050, 583750],
'head_household': [63000, 551350],
'married_separate': [47025, 291850]
};
var limits = brackets[status];
var tax = 0;
var incomeStart = baseIncome;
var incomeEnd = baseIncome + gainAmount;
// We iterate through the chunk of money represented by the Gain,
// determining which part falls into 0%, 15%, or 20% buckets.
// Bucket 1: 0% (From $0 to Limit[0])
var limit15 = limits[0];
var limit20 = limits[1];
var remainingGain = gainAmount;
var currentLevel = incomeStart;
// Check 0% Bucket
if (currentLevel < limit15) {
var roomInZero = limit15 – currentLevel;
var amountAtZero = Math.min(remainingGain, roomInZero);
// Tax is 0
remainingGain -= amountAtZero;
currentLevel += amountAtZero;
}
if (remainingGain <= 0) return tax;
// Check 15% Bucket
if (currentLevel < limit20) {
var roomInFifteen = limit20 – currentLevel;
var amountAtFifteen = Math.min(remainingGain, roomInFifteen);
tax += amountAtFifteen * 0.15;
remainingGain -= amountAtFifteen;
currentLevel += amountAtFifteen;
}
if (remainingGain <= 0) return tax;
// Check 20% Bucket
// Anything left is taxed at 20%
tax += remainingGain * 0.20;
return tax;
}
// Logic: Calculate Ordinary Income Tax (Standard Brackets 2024)
// Note: simplified to standard brackets, standard deduction not applied here as user inputs "Taxable Income"
function calculateOrdinaryIncomeTax(taxableIncome, status) {
// 2024 Ordinary Income Brackets (Taxable Income)
// Rates: 10%, 12%, 22%, 24%, 32%, 35%, 37%
var brackets = [];
if (status === "single" || status === "married_separate") {
// Married separate is mostly similar to single for brackets usually, simplified here to Single for code brevity
// Actually Married Separate has lower thresholds for higher brackets, but using Single logic for demo robustness
brackets = [
{ limit: 11600, rate: 0.10 },
{ limit: 47150, rate: 0.12 },
{ limit: 100525, rate: 0.22 },
{ limit: 191950, rate: 0.24 },
{ limit: 243725, rate: 0.32 },
{ limit: 609350, rate: 0.35 },
{ limit: Infinity, rate: 0.37 }
];
if(status === "married_separate") {
// Adjust top bracket for separate if strictly needed, but roughly matches single until 37%
brackets[5].limit = 304675;
}
} else if (status === "married_joint") {
brackets = [
{ limit: 23200, rate: 0.10 },
{ limit: 94300, rate: 0.12 },
{ limit: 201050, rate: 0.22 },
{ limit: 383900, rate: 0.24 },
{ limit: 487450, rate: 0.32 },
{ limit: 731200, rate: 0.35 },
{ limit: Infinity, rate: 0.37 }
];
} else if (status === "head_household") {
brackets = [
{ limit: 16550, rate: 0.10 },
{ limit: 63100, rate: 0.12 },
{ limit: 100500, rate: 0.22 },
{ limit: 191950, rate: 0.24 },
{ limit: 243700, rate: 0.32 },
{ limit: 609350, rate: 0.35 },
{ limit: Infinity, rate: 0.37 }
];
}
var tax = 0;
var previousLimit = 0;
for (var i = 0; i previousLimit) {
var taxableAtThisRate = Math.min(taxableIncome, limit) – previousLimit;
tax += taxableAtThisRate * rate;
previousLimit = limit;
} else {
break;
}
}
return tax;
}