Tile project cost estimator
20 m² of floor with 10% cutting waste means pricing 22 m² of tile, while the thinset and grout totals you already know are added without extra waste. You get one materials total and its cost per square metre. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Area
- 20
- Tile price
- 28.5
- Thinset cost
- 45
- Grout cost
- 32
- Waste percent
- 10
- Waste factor
- 1.1
- Waste area
- 2
- Area with waste
- 22
- Tile cost
- 627
Budgeting a floor or wall tile job is easy to underestimate when you only multiply bare area by the sticker price of the tile and forget waste, adhesive, and grout. This tile project cost estimator turns five practical numbers into a clear materials total: the tiled surface area, the unit price of tile per square unit, the project total for thinset or adhesive, the project total for grout, and a cutting waste percent that inflates only the tile line. It multiplies area by one plus waste over one hundred, multiplies that coverage by the tile unit price, then adds the thinset and grout totals you already worked out from bag counts or quotes. Keep area and tile price in one unit system—square metres with price per square metre, or square feet with price per square foot—and treat waste as the allowance your installer recommends for the pattern and room shape you chose.
What a tiling materials budget really includes
Multiplying the bare floor area by the tile's shelf price is the usual way to underestimate a job, because it leaves out waste, adhesive and grout. Here the area is first raised by the waste percentage to give the coverage you actually have to buy, so 20 m² with 10% waste becomes 22 m² of tile. That coverage is multiplied by the tile's unit price, and the thinset and grout totals you worked out from bag counts or a store quote are added as they are. The result is one materials total, plus the cost per square unit so different tiles or rooms can be compared.
Keeping the numbers consistent
Area and tile price must share one system: square metres with a price per square metre, or square feet with a price per square foot. Any currency works, as long as it is the same everywhere. Choose the waste your installer recommends for the pattern and the room shape, since cuts around cabinets, niches and diagonals, broken pieces and extra boxes from the same shade lot all draw on it. Thinset and grout are entered as project totals and are not inflated by waste a second time. A leftover bag can be entered at zero; negative values are rejected.
What you can do with it
DIY materials budget before buying
Enter room area, tile unit price, thinset and grout bag totals, and the waste percent your installer suggests to get a materials total before you leave the store.
Contractor room-by-room quotes
Feed each room’s area and SKU price into the same formula so purchase orders match the estimate and every waste step is auditable.
FAQ
Does waste apply to thinset and grout?
No. Cutting waste inflates only the tile coverage line. Pass thinset and grout as project totals that already include any bag-rounding buffer you want.
Which units should I use?
Any consistent pair: square metres with price per square metre, or square feet with price per square foot. Currency is yours; do not mix area systems.
What happens if area is zero or negative?
Area must be strictly positive; zero or negative surface would make a non-physical coverage target.
What does it cost?
The browser tool is free and runs locally.
Does the estimate include installation labor?
No. The result is a materials total: tile with its waste allowance, plus the thinset and grout amounts you entered. Add labor or your installer's quote separately once you have this figure.
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/tile-project-cost \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"area":20,"tile_price":28.5,"thinset_cost":45,"grout_cost":32,"waste_percent":10}'const res = await fetch("https://api.kit.forhosting.com/home/tile-project-cost", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"area": 20,
"tile_price": 28.5,
"thinset_cost": 45,
"grout_cost": 32,
"waste_percent": 10
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/home/tile-project-cost",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"area": 20,
"tile_price": 28.5,
"thinset_cost": 45,
"grout_cost": 32,
"waste_percent": 10
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/home/tile-project-cost", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"area":20,"tile_price":28.5,"thinset_cost":45,"grout_cost":32,"waste_percent":10}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"area":20,"tile_price":28.5,"thinset_cost":45,"grout_cost":32,"waste_percent":10}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/home/tile-project-cost", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"area": 20,
"tile_price": 28.5,
"thinset_cost": 45,
"grout_cost": 32,
"waste_percent": 10
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "home.tile_project_cost",
"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 powers the free browser tool and the paid API, so a phone check in the showroom matches the line item a script posts later. Non-positive area and negative prices or waste are rejected with invalid_input instead of a silent nonsense total. Successful API calls use the published base of $0.002 per item; validation failures are not charged.
How the tile project cost formula works
Start from the materials identity used on every retail and contractor take-off for ceramic, porcelain, natural stone, and mosaic work: tile material cost is the coverage you must buy times the unit price of the tile, plus the adhesive and grout you will open for that job. Tile price, thinset cost, grout cost, and waste percent must be non-negative so a zero-waste perfect rectangle and a free leftover bag remain expressible without inventing negative money. Write waste_factor equals one plus waste_percent divided by one hundred, so ten percent waste means you plan for one hundred ten percent of the bare tiled area. Multiply bare area by that factor to obtain area_with_waste—the effective tile coverage target after cuts around cabinets, niches, diagonals, broken pieces, and shade-lot extras. Multiply area_with_waste by tile_price to produce tile_cost in the same currency as the unit price. Add thinset_cost and grout_cost as project totals (bags times bag price, or a supplier lump sum) without re-applying the waste factor, because bag purchases for thinset and grout usually already include their own rounding and a second waste pass would double-count allowance. The response also echoes waste_area, materials_total, and cost_per_area so you can audit the math against a hand calculation on the packing slip and compare jobs of different sizes on a per-square-unit basis. The pipeline is deterministic floating-point arithmetic with no random seeds, no wall-clock timestamps, and no network calls, so identical inputs always produce identical JSON. Area must be strictly positive: zero or negative surface is rejected with invalid_input because coverage would be non-physical.
What you send and what you get back
All five fields are required. Send five finite numbers: area for the bare tiled surface in square units, tile_price for the unit price of tile per matching square unit, thinset_cost for the adhesive materials total, grout_cost for the joint materials total, and waste_percent as the extra tile percentage (for example ten for a ten percent cutting allowance). Aliases such as surface, sqm, price_per_area, adhesive_cost, joint_cost, and waste_pct are accepted so forms and query strings can reuse the same contract. Missing fields, non-numeric strings, NaN, and Infinity fail with invalid_input and are not charged. When area is zero or negative the request fails with a message that area must be positive, so clients can correct dimensions before retrying instead of receiving a zero or negative total. When any cost or waste field is negative the request fails naming that field. On success the response echoes cleaned inputs, waste_factor, waste_area, area_with_waste, tile_cost, materials_total, cost_per_area (materials_total divided by bare area), a unit_note reminder to keep one area and price system, and a short formula string for documentation. Classic checks include a twenty square-metre room at twenty-eight point five currency units per square metre, ten percent waste, forty-five for thinset, and thirty-two for grout: area with waste is twenty-two, tile cost is six hundred twenty-seven, and materials total is seven hundred four. Pricing for successful API calls is the published base of $0.002 per item; validation failures do not consume prepaid balance.
Where tile project cost estimates show up in real work
Homeowners renovating kitchens, bathrooms, and laundry rooms need a trustworthy materials total before they buy large-format porcelain with a high unit price and a long lead time, especially when thinset and grout are easy to forget at the counter. Flooring and tile contractors build room schedules from measured areas and supplier unit prices; a single deterministic endpoint that inflates only the tile line reduces spreadsheet drift between the estimator and the purchasing clerk. Interior designers comparing three tile SKUs for the same plan can swap only tile_price while holding area, waste, thinset, and grout fixed, then rank materials_total and cost_per_area without re-deriving the waste math each time. Property managers planning multi-unit refreshes feed a batch of room areas and SKU prices through the API and attach materials_total to purchase orders so overstock stays intentional rather than accidental. Because this capability is a pure parse engine, API pricing is the published base of $0.002 per successful item and failed validation does not consume balance. If you later need tile piece counts, wall openings, or geometric grout kilograms, treat those as separate search intents and landings—home.floor_tiles, home.wall_tiles, and home.tile_grout—rather than overloading this materials-cost page with layout geometry.
Integration use cases
SKU comparison for designers
Hold area, waste, thinset, and grout fixed, swap tile_price across candidate products, and compare materials_total and cost_per_area side by side.
Technical questions
How does this tile project cost estimator work?
It inflates bare area by (1 + waste_percent/100), multiplies by tile_price for the tile line, then adds thinset_cost and grout_cost as project totals to produce materials_total and cost_per_area.