Scope
One-time fees to entitle and build. Entitlement and environmental review, building and trade permits, site and engineering permits, connection and impact fees, and posted assurances.
Not recurring costs: no utility service, property tax, business licence renewals, or annual inspections. And not construction cost — a state DOT access permit is a few hundred dollars, while the turn lanes it requires are not a fee at all.
Every dollar carries a citation
Each line records a source URL, document, section, adoption date, and a confidence level:
- verified read off the named ordinance
- benchmark industry-typical placeholder, not this jurisdiction's figure
- estimated derived or interpolated
- unknown nobody has checked
Confidence is reported in dollars, not line counts. "48 of 60 lines verified" sounds reassuring while hiding that the twelve unverified ones are most of the money.
Three things that are easy to get wrong
A $0 line is not an answer
A plumbing permit priced per fixture, run against a project where nobody filled in the fixture count, returns $0 — and $0 looks like a result. Those are surfaced as explicit warnings, and the command-line runner exits non-zero so it can sit in a pipeline that fails loudly.
A bond is not a fee
A letter of credit is posted as security and released on acceptance, so its face value never enters the fee total. Its premium does — roughly 1–2% per year of face value, which the fee schedule never mentions.
An estimate is not a budget
Fees are paid at permit issuance, not at underwriting, so they are escalated forward to the expected permit date. A contingency is then applied to fees plus bond premium together. Both conventions come from real fee checklists; on the worked example they move the number by about 31%.
Redevelopment credits
The existing meter earns a water and sewer capacity credit; the prior use's traffic offsets the transportation impact fee. Both are routinely left on the table, because claiming them requires knowing the existing meter size and the prior use. A credit is capped at the gross so a fee can never go negative.
Valuation is not one number
Jurisdictions variously take the contractor's declared price, compute it themselves from a $/sf table, or take the greater of the two. Each schedule declares which. The table is the published ICC Building Valuation Data, with an explicit escalation factor rather than adjusted numbers baked in invisibly.
Trip generation
Transportation impact fees are assessed on net new PM peak hour trips. ITE rates here are editable defaults drawn from publicly filed traffic studies, not a licensed reproduction of the Trip Generation Manual. Where an ordinance names a specific ITE edition and land use code, that frozen rate governs and should be set as an override.
Reading Confirm Entities
The roster is fixed. [5] lists thirteen categories — Zoning, Building, Water, Sewer, Stormwater, Electric, Gas, Schools, Roads, Parks, Fire, Health, Housing — every one of them, whether or not anything was found. An empty Water row reading LOW is the tool advertising a gap; an absent row would hide one. Anything the resolution ladder found that fits none of the thirteen, and any service the schedule prices that none of them covers, is listed below Housing rather than dropped, and a conservation line at the foot of the section says so in numbers.
Confidence is derived, never authored. There is no confidence field in any data file. Each row's level is a pure function of statuses the engine already computes: LOW — no specific body named, or a body named whose status is unresolved or absent, so nothing sourced establishes it bills here; MODERATE — a body named and sourced, but either no governing document was located or the strongest source form is an API, HTML or rendered-DOM capture, a live page that can change under its own citation after it is cited; HIGH — a governing document located as a fixed artefact, a regulator filing or an archived PDF, which cannot. Source forms rank regulator filing > archived PDF > API > HTML > rendered DOM, and the strongest decides. The dividing line is whether the document can change under its own citation.
Existence is not assignment. "Which county, township and incorporated place contain this point" is precisely what the Census Geocoder determines, so in [4] a geocoder match is the governing determination and reads HIGH — there is no separate document to go and find. In [5] the same geocoder establishes only that a body exists here and says nothing about who bills, so that tier alone never reaches HIGH on a service. Township is listed in [4] on purpose: every point in Indiana and Ohio falls in one and it genuinely governs, most often fire protection and poor relief.
A decision is recorded against the body, not the category. Confirm,
Modify and Not Applicable confirm who a body is and that it is present here.
One body can sit in two categories — Hancock County is both the County row
and the Health row — and deciding it once decides it in both. That is not a
claim that the body bills for the category; no button on the page can make
one. The link identifies the body, not the document: a utility's homepage is
a valid confirmation, and a confirmed body with a blocked document is a
normal state, which is why entity status and document status are kept
separate. Entity confirmation stays out of verified_pct, because
confirming who bills is not the same act as confirming a number.
Two bodies on one row: alternatives or co-billers. A city MS4
utility and a county drainage board can both bill the same parcel for
different pieces; a town sewer department and a private utility that split
the town by territory are candidates for one slot. The page says which,
and derives it rather than assuming: from the jurisdiction's record when
it states the relationship (McCordsville's sewer, from Aqua Indiana's own
service-territory page), otherwise from the bodies' kinds (several of one
kind are candidates for one slot by construction), otherwise from the
service registry's multiple_common flag — whether the service
is normally billed by more than one body on the same parcel. When none of
those settles it, the row says so instead of picking. On an alternatives
row confirming one body resolves the others — a derived state, not a stored
decision, so undoing the confirmation makes them candidates again; on a
co-billers row each is confirmed on its own.
What the reader can add. A body, by link, on any row — the link identifies the body, so a pasted URL plus a name (pre-filled from the page title when one can be fetched, always editable) is a complete claim. It renders attested: no document produced it, it sits below anything cited, and the row's confidence is still derived from cited evidence alone. After ingest it also lands on the jurisdiction's artifact as an attested entity, which is exactly what document discovery needs to start a fee-schedule hunt. And an empty row can be marked not applicable — "no body bills this here" — recorded at the category level because there is no body to record it against. Neither claim can hide a finding: a not-applicable mark over a row where the ladder or the artifact names a body is shown as a conflict, both sides visible, until the reader withdraws one. Both travel through the same export → ingest path as every other decision, and corrections never auto-apply.
Two engines, held together
The estimator exists twice: Python for the CLI and reports, JavaScript so this site computes instantly in the browser. The JS holds logic only — every fee schedule, rate table, and default is exported from Python, and expressions are parsed in Python and shipped as a syntax tree, so the browser never parses anything. The two are held to each other by a line-by-line parity check.
What it cannot do
- Resolve a parcel to a special district boundary. No national dataset exists. See Who Bills for how to find them.
- Know about recapture agreements. They appear in no fee schedule — only on a title commitment or in the city engineer's memory.
- Price a negotiated contribution. Traffic signal money and development agreement terms come out of a negotiation, not a schedule.