🏠 Home Loan Calculator

Calculate your monthly mortgage payments, check how much home you can afford, explore early payoff savings, or compare refinancing options. Select a tab and enter your details below.

i
Modify the values and click the Calculate button to use
PKR
PKR
%
PKR
PKR/mo
PKR
PKR
PKR
%
PKR
%
PKR
PKR
%
%
PKR
$
Results
🏡

Enter your loan details on the left
and click Calculate to see results.

`; } function renderResults(mainValue, mainLabel, rows, barData, note, amort) { const barHTML = barData ? `
${barData.aLabel} ${barData.bLabel}
` : ''; const rowsHTML = rows.map(r => `${r.label}${r.value}`).join(''); const amortHTML = amort ? buildAmort(amort) : ''; const noteHTML = note ? `
${note}
` : ''; document.getElementById('result-content').innerHTML = `
${mainValue}
${mainLabel}
${barHTML}
Loan Summary
${rowsHTML}
${amortHTML} ${noteHTML}`; } function buildAmort(schedule) { const rows = schedule.slice(0, 24).map(r => `${r.month}${fmtN(r.payment)}${fmtN(r.principal)}${fmtN(r.interest)}${fmtN(r.balance)}` ).join(''); return `
Amortization Schedule
${rows}
Mo.PaymentPrincipalInterestBalance

Showing first 24 months · Amounts in PKR

`; } function makeAmort(principal, annualRate, years) { const r = annualRate / 100 / 12; const n = years * 12; const p = pmt(principal, annualRate, years); let bal = principal; const sched = []; for (let i = 1; i <= n; i++) { const interest = bal * r; const princ = p - interest; bal -= princ; sched.push({ month: i, payment: p, principal: princ, interest, balance: Math.max(0, bal) }); } return sched; } function calculate(type) { if (type === 'monthly') { const price = +document.getElementById('price-m').value || 0; const down = +document.getElementById('down-m').value || 0; const rate = +document.getElementById('rate-m').value || 0; const term = +document.getElementById('term-m').value; const tax = +document.getElementById('tax-m').value || 0; const ins = +document.getElementById('ins-m').value || 0; const loan = price - down; if (loan <= 0) { alert('Down payment must be less than home price.'); return; } const monthly = pmt(loan, rate, term); const total = monthly * term * 12; const totalInt = total - loan; const full = monthly + tax + ins; const amort = makeAmort(loan, rate, term); lastResults = { type, price, down, loan, rate, term, monthly: full, total, totalInt }; renderResults( fmt(full) + ' / mo', 'Estimated Monthly Payment' + (tax || ins ? ' (incl. tax & insurance)' : ''), [ { label: 'Home Price', value: fmt(price) }, { label: 'Down Payment', value: fmt(down) + ' (' + ((down/price)*100).toFixed(1) + '%)' }, { label: 'Loan Amount', value: fmt(loan) }, { label: 'Annual Interest Rate', value: rate + '%' }, { label: 'Loan Term', value: term + ' years' }, { label: 'Principal & Interest', value: fmt(monthly) + ' / mo' }, { label: 'Tax + Insurance', value: fmt(tax + ins) + ' / mo' }, { label: 'Total Interest Paid', value: fmt(totalInt) }, { label: 'Total Cost of Loan', value: fmt(total) }, ], { pct: (loan / total * 100).toFixed(1), aLabel: 'Principal: ' + fmt(loan), bLabel: 'Interest: ' + fmt(totalInt) }, 'This estimate assumes a fixed interest rate. Actual payments may vary based on your lender\'s terms, insurance premiums, and applicable taxes.', amort ); } else if (type === 'affordability') { const income = +document.getElementById('income-a').value || 0; const debts = +document.getElementById('debts-a').value || 0; const down = +document.getElementById('down-a').value || 0; const rate = +document.getElementById('rate-a').value || 0; const term = +document.getElementById('term-a').value; const dti = +document.querySelector('input[name="dti-a"]:checked').value / 100; const maxPmt = income * dti - debts; if (maxPmt <= 0) { alert('Your existing debts exceed the affordability limit at this DTI ratio.'); return; } const r = rate / 100 / 12, n = term * 12; const maxLoan = r === 0 ? maxPmt * n : maxPmt * (1 - Math.pow(1 + r, -n)) / r; const maxPrice = maxLoan + down; const totalInt = maxPmt * n - maxLoan; lastResults = { type, income, debts, down, rate, term, dti, maxPmt, maxLoan, maxPrice, totalInt }; renderResults( fmt(maxPrice), 'Maximum Affordable Home Price', [ { label: 'Monthly Income', value: fmt(income) }, { label: 'Monthly Debts', value: fmt(debts) }, { label: 'DTI Ratio Applied', value: (dti * 100) + '%' }, { label: 'Max Monthly Payment', value: fmt(maxPmt) }, { label: 'Down Payment', value: fmt(down) }, { label: 'Max Loan Amount', value: fmt(maxLoan) }, { label: 'Max Home Price', value: fmt(maxPrice) }, { label: 'Est. Total Interest', value: fmt(totalInt) }, ], { pct: (down / maxPrice * 100).toFixed(1), aLabel: 'Down Payment: ' + fmt(down), bLabel: 'Loan: ' + fmt(maxLoan) }, 'Debt-to-Income (DTI) ratio measures your monthly debt payments against your gross income. Most lenders prefer a DTI of 43% or lower.', null ); } else if (type === 'payoff') { const loan = +document.getElementById('loan-p').value || 0; const rate = +document.getElementById('rate-p').value || 0; const term = +document.getElementById('term-p').value; const extra = +document.getElementById('extra-p').value || 0; const freq = document.querySelector('input[name="freq-p"]:checked').value; const r = rate / 100 / 12, n = term * 12; const basePmt = pmt(loan, rate, term); const totalNormal = basePmt * n; const intNormal = totalNormal - loan; const extraMo = freq === 'monthly' ? extra : extra / 12; let bal = loan, months = 0, totalPaid = 0; while (bal > 0.01 && months < n * 2) { const interest = bal * r; let payment = basePmt + extraMo; if (bal + interest < payment) payment = bal + interest; bal = bal + interest - payment; totalPaid += payment; months++; } const intNew = totalPaid - loan; const intSaved = intNormal - intNew; const moSaved = n - months; const yrSaved = Math.floor(moSaved / 12); const remMo = moSaved % 12; lastResults = { type, loan, rate, term, extra, freq, basePmt, intNormal, intNew, intSaved, months }; renderResults( fmt(intSaved) + ' saved', `Pay off ${yrSaved} yr${yrSaved !== 1 ? 's' : ''} ${remMo} mo${remMo !== 1 ? 's' : ''} earlier`, [ { label: 'Loan Amount', value: fmt(loan) }, { label: 'Annual Rate', value: rate + '%' }, { label: 'Original Term', value: term + ' years' }, { label: 'Original Monthly Payment', value: fmt(basePmt) }, { label: 'Extra Payment', value: fmt(extra) + ' / ' + freq }, { label: 'New Monthly Payment', value: fmt(basePmt + extraMo) }, { label: 'New Payoff Time', value: Math.floor(months/12) + ' yrs ' + (months%12) + ' mos' }, { label: 'Time Saved', value: yrSaved + ' yrs ' + remMo + ' mos' }, { label: 'Original Total Interest', value: fmt(intNormal) }, { label: 'New Total Interest', value: fmt(intNew) }, { label: 'Interest Saved', value: fmt(intSaved) }, ], { pct: (intNew / intNormal * 100).toFixed(1), aLabel: 'Remaining interest: ' + fmt(intNew), bLabel: 'Interest saved: ' + fmt(intSaved) }, 'Making extra payments reduces your principal faster, significantly cutting total interest paid over the life of your loan.', null ); } else if (type === 'refinance') { const bal = +document.getElementById('balance-r').value || 0; const oldRate = +document.getElementById('old-rate-r').value || 0; const oldTerm = +document.getElementById('old-term-r').value; const newRate = +document.getElementById('new-rate-r').value || 0; const newTerm = +document.getElementById('new-term-r').value; const costs = +document.getElementById('costs-r').value || 0; const oldPmt = pmt(bal, oldRate, oldTerm); const newPmt = pmt(bal, newRate, newTerm); const oldTotal = oldPmt * oldTerm * 12; const newTotal = newPmt * newTerm * 12 + costs; const moSave = oldPmt - newPmt; const breakEven = moSave > 0 ? Math.ceil(costs / moSave) : null; const lifeSave = oldTotal - newTotal; lastResults = { type, bal, oldRate, oldTerm, newRate, newTerm, costs, oldPmt, newPmt, oldTotal, newTotal, moSave, breakEven, lifeSave }; renderResults( fmt(Math.abs(moSave)) + (moSave >= 0 ? ' saved/mo' : ' more/mo'), moSave >= 0 ? 'Monthly Savings After Refinancing' : 'Monthly Increase After Refinancing', [ { label: 'Current Loan Balance', value: fmt(bal) }, { label: 'Current Rate / Term', value: oldRate + '% / ' + oldTerm + ' yrs' }, { label: 'Current Monthly Payment', value: fmt(oldPmt) }, { label: 'New Rate / Term', value: newRate + '% / ' + newTerm + ' yrs' }, { label: 'New Monthly Payment', value: fmt(newPmt) }, { label: 'Monthly Savings', value: fmt(moSave) + (moSave < 0 ? ' (increase)' : '') }, { label: 'Closing Costs', value: fmt(costs) }, { label: 'Break-Even Period', value: breakEven ? breakEven + ' months' : 'N/A' }, { label: 'Original Total Cost', value: fmt(oldTotal) }, { label: 'New Total (incl. closing)', value: fmt(newTotal) }, { label: 'Lifetime Savings', value: fmt(lifeSave) + (lifeSave < 0 ? ' (loss)' : '') }, ], moSave > 0 ? { pct: (newTotal / (oldTotal || 1) * 100).toFixed(1), aLabel: 'New total: ' + fmt(newTotal), bLabel: 'Savings: ' + fmt(lifeSave) } : null, breakEven ? `You will recoup your closing costs in ${breakEven} months. If you plan to stay in your home longer than that, refinancing is financially beneficial.` : 'The new loan does not reduce your payment. Consider negotiating a lower rate or adjusting the loan term.', null ); } } // Export TXT function exportTxt() { if (!lastResults) { alert('Please calculate first.'); return; } const content = `HOME LOAN CALCULATOR RESULTS\n${'='.repeat(30)}\n\n` + document.getElementById('result-content').innerText.replace(/\t/g, ' ') + `\n\nGenerated on ${new Date().toLocaleString()}`; const blob = new Blob([content], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = Object.assign(document.createElement('a'), { href: url, download: 'home-loan-' + new Date().toISOString().split('T')[0] + '.txt' }); document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } // Export PDF function exportPDF() { if (!lastResults) { alert('Please calculate first.'); return; } const { jsPDF } = window.jspdf; const doc = new jsPDF(); let y = 20; doc.setFontSize(20); doc.setTextColor(45, 90, 30); doc.text('Home Loan Calculator Results', 105, y, { align: 'center' }); y += 10; doc.setFontSize(9); doc.setTextColor(120, 120, 120); doc.text('Generated on ' + new Date().toLocaleString(), 105, y, { align: 'center' }); y += 12; const mainEl = document.querySelector('.result-value'); const labelEl = document.querySelector('.result-label'); if (mainEl) { doc.setFontSize(16); doc.setTextColor(74, 140, 42); doc.text(mainEl.textContent, 105, y, { align: 'center' }); y += 7; doc.setFontSize(11); doc.setTextColor(100, 100, 100); if (labelEl) { doc.text(labelEl.textContent, 105, y, { align: 'center' }); } y += 12; } doc.setFontSize(13); doc.setTextColor(0, 0, 0); doc.text('Loan Summary', 20, y); y += 8; document.querySelectorAll('.result-table tr').forEach(row => { const cells = row.querySelectorAll('td'); if (cells.length === 2) { doc.setFontSize(10); doc.setFont(undefined, 'normal'); doc.setTextColor(60, 60, 60); doc.text(cells[0].textContent, 20, y); doc.setFont(undefined, 'bold'); doc.setTextColor(74, 140, 42); doc.text(cells[1].textContent, 185, y, { align: 'right' }); doc.setDrawColor(220, 220, 220); doc.line(20, y + 2, 185, y + 2); y += 8; if (y > 270) { doc.addPage(); y = 20; } } }); const noteEl = document.querySelector('.activity-note'); if (noteEl) { y += 5; doc.setFontSize(8); doc.setFont(undefined, 'normal'); doc.setTextColor(100, 100, 100); const split = doc.splitTextToSize(noteEl.textContent, 165); doc.text(split, 20, y); } doc.save('home-loan-' + new Date().toISOString().split('T')[0] + '.pdf'); }