Building Permit Address Lookup - Open & Expired Permit Check avatar

Building Permit Address Lookup - Open & Expired Permit Check

Pricing

from $12.00 / 1,000 results

Go to Apify Store
Building Permit Address Lookup - Open & Expired Permit Check

Building Permit Address Lookup - Open & Expired Permit Check

Check an address in 10 supported US cities for building permits: permit history, open permits, and permits issued but never finaled. One verdict row per address. No homeowner personal data.

Pricing

from $12.00 / 1,000 results

Rating

0.0

(0)

Developer

Brandt May

Brandt May

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 hours ago

Last modified

Share

Check a list of street addresses against a city's building permit records and get back one verdict row per address, not a bulk permit dump. For every address this Actor reports the permit history, how many permits are still open, and - the field most people come for - whether any permit was issued, passed its expiration date, and never finaled. That last condition is the classic sign of unpermitted or unfinished work, and it is what shows up as a problem during a property sale, a title review, or an insurance inspection.

This is built for people checking specific properties: real estate agents and buyers doing pre-offer due diligence, insurance underwriters assessing a risk, title and escrow officers clearing a file, contractors checking whether a prior job at an address was ever closed out, and property managers auditing a portfolio. You submit a list of addresses and get back a verdict for each one, rather than a whole-city permit feed you then have to filter yourself.

It queries official municipal open-data portals (Socrata / SODA), normalizes every city into one schema, and tells you honestly how good each address match was.


What you get

One row per address you submit. Every row carries the verdict fields plus a nested permits array with the matching permits.

FieldTypeDescription
queryAddressstringThe address exactly as you submitted it
normalizedAddressstringThe canonical form used for matching (4414 BANISTER LN)
city, statestringThe portal that was queried
matchConfidencestringexact, normalized, fuzzy, or none - the weakest grade among the permits this row counts; see below
permitCountnumberPermits matched to this address within the lookback window
permitCapReachedbooleantrue when the portal returned maxPermitsPerAddress records for this address, so older permits were not fetched and every count in the row is a lower bound. The summary then says "at least N" (or, when none of the fetched records matched, that none matched among the records checked)
earliestPermit, latestPermitstringDate range of the matched permits (YYYY-MM-DD)
openPermitCountnumber / nullPermits not finaled, completed, withdrawn, or cancelled. Permits with neither a status nor a completion date are not counted here - see statusUnknownCount. null when the portal publishes no status
statusUnknownCountnumber / nullPermits that carry neither a status nor a completion date, so whether they are open cannot be determined (in Chicago: sign, elevator equipment, scaffolding and Easy Permit records). null when the portal publishes no status
issuedNeverFinaledCountnumber / nullOpen permits that were actually issued (not just applications in review)
expiredButOpenboolean / nulltrue when at least one permit is issued, past expiry, and never finaled. null when the portal publishes no expiration date
expiredButOpenCountnumber / nullHow many permits meet that condition
humanSummarystringA plain-English sentence you can paste into a report
verdictBasisstringStates exactly what evidence the verdict rests on for this city
permits[]arrayMatched permits: id, type, class, status, description, valuation, applied / issue / expiry / completion dates, lat/lon, source link, per-permit matchConfidence, isOpen (null when unknown) and expiredButOpen
portal, scrapedAtstringSource dataset and run timestamp

How matchConfidence works

Addresses in permit systems are typed by hand, so this Actor grades every match instead of pretending they are all equal:

  • exact - the portal's street line is character-identical to yours once case and punctuation are ignored.
  • normalized - identical after expanding abbreviations (LANE / LN, WEST / W), writing numbered streets one way (34th / 34, 3rd / 03rd, Fifth / 5), and setting aside a unit or building designator. Same property, different spelling.
  • fuzzy - same house number and street name, but one side carries tokens the other does not: a street direction you did not enter (leading, or trailing like the S in Rainier Ave S), a leading direction you entered that the portal omits, a missing street type, or extra words. Verify these before relying on them.
  • none - nothing matched. The row is still returned, with permitCount: 0.

A row's matchConfidence is the weakest grade among the permits it counts, so a row reads exact only when every permit in it matched exactly; each permit also carries its own grade.

Street directions and street types have to agree. A direction or street type that conflicts with the one you typed never matches: 500 E Cesar Chavez St does not pick up 500 W, 1000 4th Ave S does not pick up 1000 4th Ave, and 200 Park Avenue South does not pick up 200 Park Avenue. If you leave out a direction (leading or trailing), permits that add one are used only when nothing matches the address exactly as you typed it - 100 Broadway does not pick up 100 East Broadway, 1000 4th Ave does not pick up 1000 4th Ave S, 200 Park Avenue does not pick up 200 Park Avenue South. When they are used (3820 Rainier Ave finds the permits at 3820 Rainier Ave S), they are graded fuzzy and the summary names the direction you left out; when they carry more than one direction (500 E and 500 W), the summary says they may be different buildings and asks you to add it.

Numbered streets can be typed the normal way: 151 West 34th Street and 151 West 34 Street find the same New York permits.

What is deliberately NOT in the output

No homeowner names. No personal phone numbers. No personal email addresses. Several of these portals publish the property owner's name right next to the permit, and this Actor strips it. Permit party names are emitted only when the name reads as a business (Vargas Electric LLC, Kind Roofing); anything that reads as an individual is withheld and flagged with contractorNameWithheld: true.

This is the differentiator, not an oversight. Competitors in this category bolt on skip-tracing and contact enrichment, so what starts as a permit check arrives as a lead list attached to somebody's home address. This Actor does not do that. It reads public government records, returns a verdict about the property, and stops there - there is no personal-contact data in the output to strip out later, and nothing here is sourced from a private marketplace or directory. If you need homeowner contact data, this is not the tool, and that is on purpose.


Input

FieldTypeDefaultDescription
addressesarray3 sample Austin addressesStreet addresses to check, one per line. House number required; unit, city, state and ZIP are optional and ignored when matching
cityselectaustinWhich municipal portal to query. One city per run - addresses from other cities will not match
lookbackYearsinteger10How far back to search from today (1-60)
maxPermitsPerAddressinteger100Cap on permits fetched per address before matching, newest first. A row that hits it says so with permitCapReached: true
maxRunSecondsinteger240Stop cleanly at this point and keep what has been written
socrataAppTokenstringemptyOptional Socrata token to raise rate limits on long lists. Not required

Supported cities and what each one can actually tell you

Not every portal publishes the data an open/expired verdict needs. Rather than guess, this Actor returns null for verdicts a city cannot support and says so in verdictBasis and humanSummary.

CityOpen verdictExpired-but-open verdict
Austin, TXyesyes
Seattle, WAyesyes
Cincinnati, OHyesyes
New York, NYyesyes
Chicago, ILyes, except permit types published with no status (signs, elevator equipment, scaffolding, Easy Permit), which are counted in statusUnknownCountno - portal publishes no expiration date
San Francisco, CAyesno - portal publishes no expiration date
Los Angeles, CAyesno - portal publishes no expiration date
Mesa, AZyesno - portal publishes no expiration date
Baton Rouge, LAno - portal publishes no permit statusno
Marin County, CAno - portal publishes no permit statusno

Example output

A real result for 2603 Ware Rd in Austin, copied verbatim and unedited from a run of this Actor. The permits are shown in full, in the order the Actor emits them (most recent first).

{
"queryAddress": "2603 Ware Rd",
"normalizedAddress": "2603 WARE RD",
"city": "Austin",
"state": "TX",
"matchConfidence": "exact",
"permitCount": 2,
"permitCapReached": false,
"earliestPermit": "2024-01-17",
"latestPermit": "2024-02-23",
"openPermitCount": 1,
"statusUnknownCount": 0,
"issuedNeverFinaledCount": 1,
"expiredButOpen": true,
"expiredButOpenCount": 1,
"humanSummary": "2 permits on record between 2024-01-17 and 2024-02-23. 1 still open (not finaled or closed out). 1 of those is past the permit expiry date with no final inspection on record - worth investigating before closing or binding coverage.",
"verdictBasis": "open/closed derived from permit status and completion date; expiry derived from the published permit expiration date",
"lookbackYears": 10,
"permits": [
{
"permitId": "2024-004889 MP",
"permitType": "Mechanical Permit",
"permitClass": "Residential",
"status": "Final",
"workDescription": "REPLACEMENT OF LONESTAR UPFLOW NATURAL GAS 3.5 TON 15.20 SEER CONDENSOR AND 2 FLEX DUCT OUTLETS",
"sourceAddress": "2603 WARE RD",
"zip": "78741",
"valuation": null,
"contractorName": null,
"appliedDate": "2024-01-15T00:00:00.000",
"issueDate": "2024-02-23T00:00:00.000",
"expiryDate": "2024-03-01T00:00:00.000",
"completedDate": "2024-03-01T00:00:00.000",
"latitude": 30.22428863,
"longitude": -97.73227205,
"sourceUrl": "https://abc.austintexas.gov/web/permit/public-search-other?t_detail=1&t_selected_folderrsn=13265815",
"contractorNameWithheld": false,
"matchConfidence": "exact",
"isOpen": false,
"expiredButOpen": false
},
{
"permitId": "2024-004892 EP",
"permitType": "Electrical Permit",
"permitClass": "Residential",
"status": "Active",
"workDescription": "Installing an outdoor meter loop. Disconnect/Reconnect",
"sourceAddress": "2603 WARE RD",
"zip": "78741",
"valuation": null,
"contractorName": "JON WAYNE ELECTRICAL",
"appliedDate": "2024-01-15T00:00:00.000",
"issueDate": "2024-01-17T00:00:00.000",
"expiryDate": "2024-08-10T00:00:00.000",
"completedDate": null,
"latitude": 30.22428863,
"longitude": -97.73227205,
"sourceUrl": "https://abc.austintexas.gov/web/permit/public-search-other?t_detail=1&t_selected_folderrsn=13265818",
"contractorNameWithheld": false,
"matchConfidence": "exact",
"isOpen": true,
"expiredButOpen": true
}
],
"portal": "https://data.austintexas.gov/resource/3syk-w9eu",
"scrapedAt": "2026-09-24T03:28:07.832Z"
}

The second permit above - the electrical one - was issued on 2024-01-17, expired on 2024-08-10, and carries no completion date. That is what expiredButOpen: true means. The mechanical permit listed first was finaled on 2024-03-01, so it counts toward permitCount and nothing else.


FAQ

What exactly counts as an "open" permit? A permit with no completion or final-inspection date whose status is not a closed-out one (finaled, completed, closed, signed-off, withdrawn, cancelled, void, revoked, rejected, denied, or a certificate of completion or occupancy issued). A status of Expired is deliberately counted as open, because an expired permit is precisely one that was never finaled. A status that names a finished step before the permit itself is finished - Seattle's "Application Completed" and "Reviews Completed", Los Angeles's "CofO in Progress" - counts as open. Permits still in review with no issue date count as open too, and are excluded from issuedNeverFinaledCount so you can tell the two apart. A permit that carries neither a status nor a completion date is counted as neither open nor closed: its isOpen is null and it goes into statusUnknownCount.

Does expiredButOpen: true prove there is unpermitted work? No, and the Actor does not claim it does. It means the city's own published record shows a permit that was issued, has passed its expiration date, and carries no final inspection or completion date. Records also lag reality - a permit may have been finaled without the portal being updated. Treat it as a flag to investigate with the building department, not as a finding.

Why is one address fuzzy and another exact? Because permit clerks type addresses by hand. 4414 BANISTER LN BLDG 1 and 4414 Banister Ln are the same parcel but not the same string, so that match is graded normalized. A match missing a directional (1847 Newcastle Ave against 1847 N NEWCASTLE AVE) is graded fuzzy. A conflicting direction or street type (500 E against 500 W) is not a match at all. The grade is in every row and on every permit so you can decide how much to trust it.

Can I check addresses in several cities in one run? No. Each run queries one city portal, because the address filter is built for that portal's specific schema. Run the Actor once per city; results append to the same dataset if you want them together.

Why are contractor names sometimes blank? Either the portal publishes no contractor for that permit (San Francisco and Los Angeles publish none at all on these datasets), or the name looked like a person rather than a business and was withheld on purpose. contractorNameWithheld: true distinguishes the second case from the first.

What happens if the run is too slow for a long address list? It stops cleanly at maxRunSeconds, keeps every row already written, and logs how many addresses were left. Raise maxRunSeconds or split the list.


Data source, access, and limits

Permit data comes from official municipal open-data portals running Socrata (SODA), one dataset per city, listed in the table above. These are public government APIs that need no login and no API key. The optional socrataAppToken only raises rate limits on long runs; everything works without it.

That is the only source. Every field in the output traces back to a government open-data record, so there is no third-party site in the path that can rate-limit the run, block it, or change its terms underneath you. Nothing is read from a private marketplace, contractor directory, or lead broker.

Known limits. Coverage is the ten cities listed, not nationwide. Verdict quality varies by city exactly as the capability table states. Open-data portals refresh on their own schedules (typically daily to weekly), so very recent permits may not appear yet, and a permit finaled last week may still read as open. Addresses without a house number cannot be matched and are reported as errors. Large commercial parcels can exceed the default 100-permit cap - the row then says permitCapReached: true and "at least N"; raise maxPermitsPerAddress for those. New York is matched on house number and street name across all five boroughs, so the same address in two boroughs is not told apart.

Billing. This Actor is billed per result on the Apify platform: one result is one address verdict row, regardless of how many permits that address turns out to have. Addresses that fail to look up are not emitted and therefore are not charged. Check the pricing shown on the Actor's Apify Store page for the current rate.

Legal. Permit records are public government data. Nothing here is a substitute for an official records search, a title report, or a municipal building department inquiry, and none of it is legal, insurance, or investment advice.