Metal roofing panel calculator
A 1,200 square foot roof with 3 by 12 foot panels and a 0.5-foot side lap gets 30 square feet of cover per sheet, so you need 40 panels. Enter roof area, panel size and overlap to order whole sheets. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Roof area
- 1,200
- Panel width
- 3
- Panel length
- 12
- Side lap
- 0.5
- Effective panel width
- 2.5
- Coverage per panel
- 30
- Panels needed
- 40
- Total coverage area
- 1,200
Ordering metal roofing panels without accounting for side lap is a common way to underbuy material or pad every quote with guesswork. This capability takes the roof surface area, the nominal panel width and length, and the side overlap between adjacent sheets, then returns how many whole panels you need. Effective cover width is panel width minus side overlap; coverage per panel is that width times panel length; the panel count is the ceiling of roof area divided by coverage per panel. Units are yours to keep consistent: use feet with square feet, or meters with square meters, and the arithmetic stays correct.
Why side overlap changes the panel count
Metal roofing panels are sold at a nominal width, but installed courses share a side lap so water sheds correctly and seams stay sealed. That lap is not free cover: every inch of overlap is width you already paid for on one panel and do not get again as open roof area. If you divide roof area by full panel area, you systematically undercount sheets and discover the shortfall only when installers run out mid-course.
Effective panel width is therefore nominal width minus side overlap. Multiplying that effective width by panel length gives the true coverage area of one sheet. Ceiling division of roof area by that coverage yields a whole number of panels that at least matches the surface.
Excess area in the response is the overshoot from rounding up to whole sheets, which is useful when you compare manufacturers or when you decide whether a slightly wider panel reduces waste.
How to enter area, panel size and side lap
Do not mix feet and meters in a single request. Do not send side lap as a percentage unless you have already converted it to a linear width. Zero overlap is allowed for open-span or standing-seam products that the manufacturer rates as full-width cover; a positive lap is typical for ribbed and corrugated sheets.
Decimal values are fine: a twelve-hundred square foot roof with three-foot wide by twelve-foot long panels and a half-foot side lap uses an effective width of two and a half feet, coverage of thirty square feet per panel, and forty whole panels. Prefer machine numbers over strings that embed unit labels so parsers do not guess.
Where panel counts fit in real estimating pipelines
Roofing contractors convert takeoff areas into purchase orders before a crew arrives; a deterministic panel count avoids spreadsheet drift between office and field. Product pages and configurators can call the same logic when a homeowner picks panel size and lap so the cart shows sheets, not abstract square footage alone. Insurance and restoration estimators often store measured roof area and standard panel SKUs; running this transform once per line keeps quotes auditable.
Invalid inputs do not consume balance, so validate client forms aggressively. Combine the output with waste factors you apply yourself for hips and valleys if your process requires them; this capability stays focused on area, geometry and side overlap so the contract remains small and stable.
What you can do with it
Contractor material takeoff
Turn measured roof square footage and chosen panel SKU dimensions into a whole panel count that includes side lap before ordering.
FAQ
Which units should I use?
Any consistent system: square feet with feet, or square meters with meters. Do not mix units in one request. Side overlap must be a linear width, not a percentage.
What does it cost?
The page tool is free in your browser. Invalid inputs are not charged.
Why not just divide the roof area by the full panel size?
Because the side lap is not cover: that strip of each sheet sits under its neighbor. Dividing by the full panel area undercounts sheets, and the shortfall usually appears when installers run out mid-course.
Can the side overlap be zero?
Yes, for standing-seam or open-span products the manufacturer rates as full-width cover. Ribbed and corrugated sheets usually need a positive lap, and the overlap must always be smaller than the panel width.
Does the panel count include waste for ridges, hips and valleys?
No. The count covers the area you enter and nothing more, so fold the extra for ridges, hips and valleys into the roof area itself before you calculate.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/home/metal-roofing-panels \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"roof_area":1200,"panel_width":3,"panel_length":12,"side_overlap":0.5}'const res = await fetch("https://api.kit.forhosting.com/home/metal-roofing-panels", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"roof_area": 1200,
"panel_width": 3,
"panel_length": 12,
"side_overlap": 0.5
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/home/metal-roofing-panels",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"roof_area": 1200,
"panel_width": 3,
"panel_length": 12,
"side_overlap": 0.5
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/home/metal-roofing-panels", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"roof_area":1200,"panel_width":3,"panel_length":12,"side_overlap":0.5}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"roof_area":1200,"panel_width":3,"panel_length":12,"side_overlap":0.5}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/home/metal-roofing-panels", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"roof_area": 1200,
"panel_width": 3,
"panel_length": 12,
"side_overlap": 0.5
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "home.metal_roofing_panels",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
The same pure function runs in the free browser tool and on the API, so spreadsheets, intake forms and field apps stay in sync. Missing fields, non-finite numbers, non-positive dimensions, or a side overlap greater than or equal to panel width fail with invalid_input instead of inventing a count.
Why side overlap changes the panel count
The model is intentionally area-based and unit-agnostic: it does not invent ridge, hip or valley waste beyond what you fold into roof_area, so complex roofs still need a measured or projected surface area as the starting input.
How to enter area, panel size and side lap
Send roof_area as a finite positive number for the total surface you intend to cover, using one consistent system of units. panel_width and panel_length are the nominal dimensions of one panel in the matching linear unit. side_overlap is the side lap width in that same linear unit and must be zero or greater but strictly less than panel_width so effective cover stays positive. Aliases such as area, width, length, side_lap and overlap map cleanly from existing forms.
Where panel counts fit in real estimating pipelines
Batch jobs that import CSV rows from design software can map each roof polygon area into panels_needed and excess_area without floating UI code. Use the page tool for a single job, or call the API when automation needs the calculation at $0.002 per successful request.
Integration use cases
Product configurator and cart
Let shoppers pick panel width, length and lap and show panels_needed plus excess coverage without a custom spreadsheet.
Batch import from design software
Map CSV rows of roof area and panel specs into consistent panels_needed fields for quotes and warehouse picks.
Technical questions
What does this metal roofing panel calculator return?
It returns the inputs you sent, effective_panel_width (width minus side overlap), coverage_per_panel, panels_needed (ceiling of area over coverage), total_coverage_area and excess_area from rounding up.
When does the calculation fail?
It fails with invalid_input when a required field is missing or not finite, when roof_area, panel_width or panel_length is not positive, when side_overlap is negative, or when side_overlap is greater than or equal to panel_width.
Is the browser result the same as the API?
Yes. Both run the same pure function in lib.js, so identical inputs produce the same panel count and coverage figures.