<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Building Permit Cost Calculator | permitcalculator.com</title>
<style>
:root {
--primary: #2563eb;
--secondary: #1e40af;
--success: #059669;
--warning: #d97706;
--gray-900: #111827;
--gray-800: #1f2937;
--gray-700: #374151;
--gray-600: #4b5563;
--gray-500: #6b7280;
--gray-200: #e5e7eb;
--gray-100: #f3f4f6;
--white: #ffffff;
--shadow: 0 10px 15px -3px rgba(0, 0,0,0.1);
--shadow-lg: 0 25px 50px -12px rgba(0,0,0,0.25);
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; line-height: 1.6; color: var(--gray-800); background: linear-gradient(135deg, var(--gray-100) 0%, #f8fafc 100%); padding: 1rem; }
.container { max-width: 800px; margin: 0 auto; background: var(--white); border-radius: 1rem; box-shadow: var(--shadow-lg); overflow: hidden; }
.hero { background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%); color: var(--white); padding: 2rem 2rem 1.5rem; text-align: center; }
.hero h1 { font-size: clamp(1.75rem, 5vw, 2.5rem); font-weight: 700; margin-bottom: 0.5rem; }
.hero p { font-size: 1.125rem; opacity: 0.95; margin-bottom: 0.25rem; }
.hero .trust { font-size: 0.875rem; opacity: 0.8; font-weight: 500; }
.section { padding: 2rem; }
.inputs form { display: grid; gap: 1.5rem; }
label { display: flex; flex-direction: column; font-weight: 500; gap: 0.25rem; font-size: 0.95rem; }
input, select { padding: 0.75rem 1rem; border: 2px solid var(--gray-200); border-radius: 0.5rem; font-size: 1rem; transition: border-color 0.2s; }
input:focus, select:focus { outline: none; border-color: var(--primary); }
.slider-container { display: flex; align-items: center; gap: 1rem; }
input[type=range] { flex: 1; height: 6px; background: var(--gray-200); border-radius: 3px; }
.advanced { border: 2px solid var(--gray-200); border-radius: 0.75rem; padding: 1.5rem; margin-top: 1rem; background: var(--gray-100); }
.advanced h3 { margin-bottom: 1rem; font-size: 1.125rem; color: var(--gray-900); }
button { background: var(--primary); color: var(--white); border: none; padding: 1rem 2rem; border-radius: 0.5rem; font-size: 1.125rem; font-weight: 600; cursor: pointer; transition: background 0.2s; width: 100%; }
button:hover { background: var(--secondary); }
.results { background: linear-gradient(135deg, var(--success) 0%, #047857 100%); color: var(--white); text-align: center; padding: 3rem 2rem; }
.results h2 { font-size: clamp(2.5rem, 8vw, 4rem); font-weight: 800; margin-bottom: 1rem; }
.results .big-num { font-size: clamp(3rem, 10vw, 5rem); font-weight: 900; color: var(--white); }
.context { font-size: 1.125rem; margin: 1rem 0; opacity: 0.95; }
.chart-container { display: flex; justify-content: space-around; margin: 2rem 0; max-width: 500px; margin-inline: auto; }
.bar { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; flex: 1; }
.bar-label { font-weight: 600; font-size: 0.875rem; }
.bar-fill { height: 20px; background: linear-gradient(90deg, var(--primary) 0%, var(--secondary) 100%); border-radius: 10px; transition: width 0.3s; width: 0%; min-width: 20px; }
.scenarios { display: grid; gap: 1rem; margin: 2rem 0; }
.scenario { background: rgba(255,255,255,0.2); padding: 1rem; border-radius: 0.5rem; }
.share { margin-top: 1.5rem; }
.methodology { border-top: 1px solid var(--gray-200); }
details { cursor: pointer; }
summary { font-weight: 600; padding: 1rem; border-bottom: 1px solid var(--gray-200); }
.method-content { padding: 1.5rem; }
.related { display: grid; gap: 1rem; }
.related-item { padding: 1rem; background: var(--gray-100); border-radius: 0.5rem; }
.related-item a { color: var(--primary); text-decoration: none; font-weight: 600; }
@media (max-width: 640px) { .chart-container { flex-direction: column; gap: 1.5rem; } body { padding: 0.5rem; } .section { padding: 1.5rem 1rem; } }
.tooltip { position: relative; }
.tooltip-icon { font-size: 1.2em; color: var(--gray-500); cursor: help; margin-left: 0.5rem; }
.tooltip-text { visibility: hidden; position: absolute; top: 100%; left: 0; background: var(--gray-900); color: var(--white); padding: 0.5rem; border-radius: 0.25rem; font-size: 0.875rem; white-space: nowrap; z-index: 10; }
.tooltip:hover .tooltip-text { visibility: visible; }
.failure-check { background: var(--warning); color: var(--gray-900); padding: 1rem; border-radius: 0.5rem; margin: 1rem 0; }
</style>
</head>
<body>
<div class="container">
<section class="hero">
<h1>Building Permit Cost Calculator</h1>
<p>Estimate fees for remodels, additions, replacements. Base plus hidden adds totals clear.</p>
<p class="trust">Updated March 2026 | Verified municipal schedules, 15 cities</p>
</section>
<section class="section inputs">
<form id="calcForm">
<label>
City
<div class="tooltip">
<select id="city">
<option value="National Average">National Average ($507)</option>
<option value="Atlanta, GA">Atlanta, GA ($510)</option>
<option value="Austin, TX">Austin, TX ($687)</option>
<option value="Boston, MA">Boston, MA ($270)</option>
<option value="Charlotte, NC">Charlotte, NC ($269)</option>
<option value="Chicago, IL">Chicago, IL ($900)</option>
<option value="Columbus, OH">Columbus, OH ($660)</option>
<option value="Dallas, TX">Dallas, TX ($992)</option>
<option value="Denver, CO">Denver, CO ($266)</option>
<option value="Houston, TX">Houston, TX</option>
<option value="Kansas City, MO">Kansas City, MO</option>
<option value="Las Vegas, NV">Las Vegas, NV</option>
<option value="Los Angeles, CA">Los Angeles, CA</option>
<option value="Miami, FL">Miami, FL</option>
<option value="Minneapolis, MN">Minneapolis, MN</option>
<option value="Nashville, TN">Nashville, TN</option>
</select>
<span class="tooltip-icon">?</span>
<span class="tooltip-text">See full [28-city cost index](/cost-index)</span>
</div>
</label>
<label>
Project Type
<div class="tooltip">
<select id="project">
<option value="Bathroom Remodel">Bathroom Remodel</option>
<option value="Kitchen Remodel">Kitchen Remodel</option>
<option value="Roof Replacement">Roof Replacement</option>
<option value="HVAC Replacement">HVAC Replacement</option>
<option value="Water Heater Replacement">Water Heater Replacement</option>
<option value="Deck Construction">Deck Construction</option>
<option value="Home Addition">Home Addition (permit cost per sq ft)</option>
<option value="Generic Building Permit">Generic Building Permit</option>
</select>
<span class="tooltip-icon">?</span>
<span class="tooltip-text">Matches published fee schedules</span>
</div>
</label>
<label>Project Value $ <input type="number" id="value" value="15000" min="1000" step="100" placeholder="e.g. 15000"></label>
<label>Sq Ft <input type="number" id="sqft" value="500" min="0" step="10" placeholder="e.g. 500"></label>
<label>
Residential / Commercial
<select id="type">
<option value="residential">Residential</option>
<option value="commercial">Commercial</option>
</select>
</label>
<div class="advanced">
<h3>Advanced options</h3>
<label class="slider-container">
Hidden Costs Factor (%)
<input type="range" id="extras" min="30" max="60" value="45" step="5">
<span id="extrasVal">45%</span>
</label>
<div class="tooltip">
<span class="tooltip-icon">?</span>
<span class="tooltip-text">Plan review, impact fees, inspections add 30 - 60% ([ConstructionBids.ai](https://constructionbids.ai/blog/building-permit-cost-calculator-guide))</span>
</div>
</div>
<button type="button" onclick="calculate()">Calculate Permit Cost</button>
</form>
</section>
<section id="results" class="results" style="display: none;">
<h2>Your Total Permit Cost</h2>
<div class="big-num" id="total">$0</div>
<p class="context" id="context"></p>
<p class="context">National average: <strong>$507</strong>. <a href="/cities/" style="color: inherit; font-weight: 600;">Full [28-city index](/cost-index)</a></p>
<div class="failure-check">
Fees first? Contractors budgeting upfront win 23% more bids. That's your edge. - David Martinez, ConstructionBids.ai
</div>
<div class="chart-container" id="chart"></div>
<div class="scenarios">
<div class="scenario">
Digital app? Cuts processing 40 - 60%. File electronic now.
</div>
<div class="scenario">
Home addition? Permit cost per square foot runs $1 - 3 typically. Watch impact fees.
</div>
<div class="scenario">
Quote ready? <a href="/calculator/" style="color: inherit; font-weight: 600;">[Check if your quote is fair](/calculators/quote-check)</a>
</div>
</div>
<div class="share">
<button onclick="copyResults()" style="background: rgba(255,255,255,0.2); color: var(--white);">Copy My Results</button>
</div>
</section>
<section class="section methodology">
<details open>
<summary>How we calculated this</summary>
<div class="method-content">
<p>Specific fees from municipal schedules. Atlanta bathroom remodel: $510 ([Atlanta Code](https://library.municode.com/ga/atlanta/codes/code_of_ordinances?nodeId=PTIIICOORANDECO_PT8COHUDE_CH2BURE)). Austin: $687 ([Austin Fees](https://www.austintexas.gov/sites/default/files/files/Development_Services/Fees_Residential.pdf)).</p>
<p>National average $507. Verified Q1 2026 schedules. Commercial 3 - 5x residential, 1 - 2% project value ([ConstructionBids.ai](https://constructionbids.ai/blog/building-permit-cost-calculator-guide)).</p>
<p>Hidden adds 30 - 60%: plan review, impacts, inspections. Home addition permit cost scales sq ft, ~$1.20 - 2.50 base before extras.</p>
<p>Residential $1,200 - $15,000 scope-driven. Permits fell 5.8% YoY Jan 2026, 1,376,000 SAAR ([Census](https://census.gov/construction/nrc/current/index.html)).</p>
<p>Configure deeper? [Budget Configurator](/calculators/configurator). See resale? [Resale Value Calculator](/calculators/resale-value).</p>
<p>Delays kill. Month lag on $2M: $13,300 interest. - Prevesta Research.</p>
</div>
</details>
</section>
<section class="section related">
<h3>Next Steps</h3>
<div class="related-item">Full city prices: [Cities](/cities/)</div>
<div class="related-item">[Compare Financing](/calculators/financing) for project funds.</div>
<div class="related-item">[Methodology](/methodology/) details sources.</div>
</section>
</div>
<script>
const permitData = {
'Atlanta, GA': {'Bathroom Remodel':510,'Kitchen Remodel':650,'Roof Replacement':360,'HVAC Replacement':150,'Water Heater Replacement':50,'Deck Construction':510},
'Austin, TX': {'Bathroom Remodel':687,'Kitchen Remodel':741,'Roof Replacement':370,'HVAC Replacement':67,'Water Heater Replacement':67},
'Boston, MA': {'Bathroom Remodel':270,'Kitchen Remodel':395,'Roof Replacement':120,'HVAC Replacement':25,'Water Heater Replacement':25},
'Charlotte, NC': {'Bathroom Remodel':269,'Kitchen Remodel':390,'Roof Replacement':62,'HVAC Replacement':62,'Water Heater Replacement':62},
'Chicago, IL': {'Bathroom Remodel':900,'Kitchen Remodel':900,'Roof Replacement':75,'HVAC Replacement':75,'Water Heater Replacement':75,'Deck Construction':250},
'Columbus, OH': {'Bathroom Remodel':660,'Kitchen Remodel':660,'Roof Replacement':140,'HVAC Replacement':140,'Water Heater Replacement':140},
'Dallas, TX': {'Bathroom Remodel':992,'Kitchen Remodel':992,'Roof Replacement':742,'HVAC Replacement':165,'Water Heater Replacement':165},
'Denver, CO': {'Bathroom Remodel':266,'Kitchen Remodel':414,'Roof Replacement':99,'HVAC Replacement':59,'Water Heater Replacement':35},
'Houston, TX': {'Bathroom Remodel':336,'Kitchen Remodel':447,'Roof Replacement':147,'HVAC Replacement':181,'Water Heater Replacement':131},
'Kansas City, MO': {'Bathroom Remodel':114,'Kitchen Remodel':158,'Roof Replacement':58,'HVAC Replacement':71,'Water Heater Replacement':58,'Deck Construction':84},
'Las Vegas, NV': {'Bathroom Remodel':521,'Kitchen Remodel':868,'Roof Replacement':98,'HVAC Replacement':60,'Water Heater Replacement':60},
'Los Angeles, CA': {'Bathroom Remodel':614,'Kitchen Remodel':849,'Roof Replacement':266,'HVAC Replacement':60,'Water Heater Replacement':60},
'Miami, FL': {'Bathroom Remodel':370,'Kitchen Remodel':440,'Roof Replacement':150,'HVAC Replacement':110,'Water Heater Replacement':110},
'Minneapolis, MN': {'Bathroom Remodel':959,'Kitchen Remodel':1347,'Roof Replacement':232,'HVAC Replacement':133,'Water Heater Replacement':85},
'Nashville, TN': {'Bathroom Remodel':318,'Kitchen Remodel':470,'Roof Replacement':75,'HVAC Replacement':75,'Water Heater Replacement':75,'Deck Construction':115}
};
const cityAvgs = {
'National Average':507,'Atlanta, GA':510,'Austin, TX':687,'Boston, MA':270,'Charlotte, NC':269,'Chicago, IL':900,'Columbus, OH':660,'Dallas, TX':992,'Denver, CO':266,'Houston, TX':336,'Kansas City, MO':114,'Las Vegas, NV':521,'Los Angeles, CA':614,'Miami, FL':370,'Minneapolis, MN':959,'Nashville, TN':318
};
function formatCurrency(n) {
return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 0 }).format(n);
}
function getBaseFee(city, project, value, sqft, isCommercial) {
const specific = permitData[city]?.[project];
if (specific) return specific;
const avg = cityAvgs[city] || 507;
const percValue = isCommercial ? 0.02 * value : 0.012 * value;
const minBase = Math.max(avg, percValue);
if (project === 'Home Addition') {
return Math.max(minBase, sqft * 1.5);
}
if (project === 'Deck Construction') {
return Math.max(avg * 1.2, percValue * 0.5);
}
return minBase;
}
function calculate() {
const city = document.getElementById('city').value;
const project = document.getElementById('project').value;
const value = parseFloat(document.getElementById('value').value) || 15000;
const sqft = parseFloat(document.getElementById('sqft').value) || 0;
const isCommercial = document.getElementById('type').value === 'commercial';
const extrasPct = parseFloat(document.getElementById('extras').value) || 45;
<aside class="bqj-expert-insert" data-expert-label="Chuck's Take">
**Chuck's Take:** Dallas wants nine ninety-two for a permit and Denver wants two sixty-six. Same country. Same code book, give or take. I promise you the inspectors in Denver are no less thorough.
* - Leonard "Chuck" Thompson, LC Thompson Construction Co.*
</aside>
const base = getBaseFee(city, project, value, sqft, isCommercial);
const extras = base * (extrasPct / 100);
const total = base + extras;
const natAvg = 507;
const variance = ((total - natAvg) / natAvg * 100).toFixed(0);
document.getElementById('total').textContent = formatCurrency(total);
document.getElementById('context').innerHTML = `That's ${variance > 0 ? '+' : ''}${variance}% vs national. ${sqft > 0 && project === 'Home Addition' ? `Building permit cost per square foot: ${formatCurrency(total / sqft)}.` : ''}`;
// Chart bars
const chart = document.getElementById('chart');
chart.innerHTML = `
<div class="bar">
<div class="bar-label">Base Fee</div>
<div class="bar-fill" data-width="${(base / total * 100)}" style="background: rgba(255,255,255,0.3);">${formatCurrency(base)}</div>
</div>
<div class="bar">
<div class="bar-label">Hidden Fees</div>
<div class="bar-fill" data-width="${(extras / total * 100)}">${formatCurrency(extras)}</div>
</div>
<div class="bar">
<div class="bar-label">Total</div>
<div class="bar-fill" data-width="100" style="background: rgba(255,255,255,0.5);">${formatCurrency(total)}</div>
</div>
`;
setTimeout(() => {
document.querySelectorAll('.bar-fill').forEach(bar => {
bar.style.width = bar.dataset.width + '%';
});
}, 100);
<aside class="bqj-expert-insert" data-expert-label="Chuck's Take">
**Chuck's Take:** That national average of five oh seven is a nice round number for a website. It has almost nothing to do with what you'll actually write a check for. Plan review fees, re-inspection fees, impact fees if you're in a growth corridor. I've pulled permits that started at four hundred and finished north of two thousand once the county got done stacking line items. Call your building department before you budget a single dollar.
* - Leonard "Chuck" Thompson, LC Thompson Construction Co.*
</aside>
document.getElementById('results').style.display = 'block';
window.scrollTo({ top: document.getElementById('results').offsetTop - 100, behavior: 'smooth' });
}
function copyResults() {
const total = document.getElementById('total').textContent;
const context = document.getElementById('context').textContent;
navigator.clipboard.writeText(`My permit cost: ${total}. ${context}`);
alert('Results copied!');
}
<aside class="bqj-expert-insert" data-expert-label="Chuck's Take">
**Chuck's Take:** I know people see a number like nine hundred in Chicago and think they'll just skip the permit on a small remodel. Let me be clear. The permit is not the expense. The permit is the receipt that says your work was done to code. The real expense comes when you sell the house and the buyer's inspector finds unpermitted work. Your closing price drops by ten times what that permit would have cost you. Pay the fee.
* - Leonard "Chuck" Thompson, LC Thompson Construction Co.*
</aside>
// Auto calc on change
document.querySelectorAll('#calcForm input, #calcForm select').forEach(el => {
el.addEventListener('change', calculate);
el.addEventListener('input', () => {
document.getElementById('extrasVal').textContent = document.getElementById('extras').value + '%';
});
});
// Init
calculate();
</script>
</body>
</html>
Building Permit Cost Calculator | Free Online Tool
· 8 min read
Methodology reviewed by David Olson, Built permit fee database from primary municipal sources ·
Continue your research