US Building Permits Scraper - 10 Cities, One Schema
Pricing
from $1.80 / 1,000 results
US Building Permits Scraper - 10 Cities, One Schema
Scrape US building permits from 10 city open-data portals into one clean schema. Contractor and applicant leads with address, valuation, and dates. Filter and export to CSV.
Pricing
from $1.80 / 1,000 results
Rating
0.0
(0)
Developer
Brandt May
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share

Compare permits across local sources
For construction and local-market research: collect building permit records from ten supported city and county open-data portals into one consistent table. Addresses, dates, declared valuation and contractor fields depend on what each source publishes.
Open this Actor in Console · First run · Results · Cost · Full guide
Try this Actor
- First run: Choose one supported source in Cities and review the per-city result cap before the first run. Inspect its mapped fields and date coverage before expanding to the full source list.
- Read the results: Open the default Dataset for permit rows and SUMMARY for per-source coverage. Use the permit ID and official record link when following up on a project.
- Keep in mind: Coverage is limited to the listed portals, not all US permits. Declared valuation is not actual spend, contractor names are not always available, and a permit alone does not establish purchasing intent or vendor-selection timing.
Result preview
The dataset view highlights these columns:
- Source city ·
sourceCity - Permit ID ·
permitId - Permit type ·
permitType - Permit class ·
permitClass - Status ·
status - Work description ·
workDescription
Use the original source links and the field definitions below when interpreting the results. CSV works well for flat columns; JSON preserves nested values.
Usage and pricing
Base result rate on the FREE tier: $3 per 1,000 results. The Pricing tab shows your plan's result rate and any Actor Start charge. Set a small result limit for the first run; the requested limit is not a guarantee of that many results.
Customer workflow: A weekly construction project review queue
Collect a bounded issue-date slice from one service-area portal, reconcile repeat permits into one row, and send a reviewed project shortlist to your team rather than appending duplicate leads.
Setup: Connect your own Apify and Google Sheets project register or CRM staging table through Make or n8n. Keep credentials in your connector's credential manager.
{"cities": ["chicago"],"issuedSince": "2026-10-01","issuedUntil": "2026-10-12","permitTypeKeywords": [],"onlyWithContractor": false,"maxResultsPerCity": 100,"maxRunSeconds": 240,"includeRaw": false}
Start with a 300-second Run timeout and $0.50 maximum run charge, alongside the input's 240-second budget. Check current pricing and the selected scope before increasing either limit.
- Create a Projects sheet and run the bounded example above. Its dates are fixed examples: replace them with your intended issue-date window. Use a rolling overlap for repeat collection, while recognizing that older revisions can still be missed.
- Review
SUMMARY.failedSources,perCity,stoppedEarlyOnTimeLimit, andstoppedOnChargeLimit. This Actor has no SUMMARY status/incomplete fields. A per-city count at your cap means a sample; narrower dates can help inspect the rest. - Create
record_keyfromJSON.stringify([sourceCity, String(permitId)]). Upsert that key using Sheets "Append or Update Row" in n8n, or a key lookup/update branch in Make. Quarantine missing permit IDs; an address alone is not a safe identity. - Queue new keys or changed business fields for review. Compare status, work description, address, valuation, contractor and dates; exclude
scrapedAt. Keep source links so a person can qualify the project before any outreach.
| Destination information | Actor fields |
|---|---|
| Source plus permit identity | sourceCity, permitId |
| Project | permitType, workDescription, status |
| Location | address |
| Published project details | valuation, contractorName |
| Dates and source | issueDate, appliedDate, sourceUrl, scrapedAt |
Keep the meaning: Deduplication lives in your destination; this Actor has no native change-only mode. Ten portals are supported, with at most 50,000 source rows scanned per city. Even output below your cap does not certify an exhaustive date window. Declared valuation is not actual spending or buying intent.
Empty or interrupted runs: A clean empty run can mean no matching inspected permits. Preserve old projects. A time/spending stop or failed source needs review, even when the run saved useful rows.
Reliable delivery: Read the completed run's own SUMMARY and paginated dataset. Retain its run ID; if destination delivery fails, replay that dataset and deduplicate by run ID plus row key. Keep destination writes sequential, and write source text literally.
Validation: Inputs and mappings were checked locally against this Actor. The exact customer connection has not been run end to end. Choose recurrence after a manual bootstrap; this guide creates no schedule. See the run API, pagination guide, and the full Actor guide below for detailed setup and limits.
Full guide
Pull building permits from 10 US city open-data portals into a single normalized dataset - built for construction lead generation and sales-territory monitoring.
What it does
This building permits scraper aggregates permit records from 10 official US city open-data portals and normalizes them into one clean schema, so you never have to reconcile a different field layout for every city. It pulls high-intent construction data - permit type, status, address, valuation, dates, and (where the city publishes it) contractor and applicant names - and lets you filter by city, minimum project value, keyword, contractor presence, and issue-date range. Use it as a lightweight US building permits API for construction lead generation, then export straight to CSV, JSON, or Excel from the Apify dataset.
The moat is the per-city field mapping: each source portal labels its columns differently, and this actor maps all of them into the same output fields so your CRM, spreadsheet, or pipeline sees consistent building permit data by city.
Who it's for
- Construction lead-gen teams sourcing new-project and renovation leads
- Contractors and subcontractors watching their service area for fresh permits
- Building-material suppliers and distributors timing outreach to project starts
- Roofers, solar installers, and HVAC sales teams chasing permit-triggered demand
- Real-estate and proptech teams enriching properties with permit activity
- Market researchers and analysts tracking construction volume by city
What you get / Output
Every record is normalized to the same fields across all 10 cities:
| Field | Description |
|---|---|
permitId | Official permit identifier from the source city |
permitType | Type/category of permit (new build, alteration, etc.) |
permitClass | Class, work type or use of the permit, as the city labels it |
status | Current permit status |
workDescription | Work description / scope text |
address | Street address of the permitted work |
city | The source portal's city (or county, for Marin County) |
state | US state |
zip | ZIP / postal code |
valuation | Declared project value or estimated cost |
contractorName | Contractor on the permit (where the city publishes it), with stray quote marks removed; placeholders such as "N/A" are left empty |
applicantName | Applicant / filer on the permit (where the city publishes it), cleaned the same way |
issueDate | Date the permit was issued |
appliedDate | Date the permit was filed / applied |
latitude | Latitude of the site |
longitude | Longitude of the site |
sourceCity | Which of the 10 source portals the record came from |
sourceUrl | Link back to the record on the source portal, where the city provides one |
scrapedAt | When the record was collected |
Note: not every city publishes every field.
contractorName,applicantName, andvaluationavailability varies by source portal - the actor fills what the city exposes and leaves the rest empty rather than inventing data.
Input / How to query
Configure a run with these filters and modes:
- Cities - choose one, several, or all 10 supported portals
- Minimum job valuation - keep only projects at or above a dollar threshold
- Permit type keywords - match against the permit type, work description and class (e.g.
roof,solar,remodel) - Only permits with a contractor name - drop permits that name no contractor
- Issued since / Issued until - restrict by issue date
- Multi-city pull - fetch several cities in a single run; each city's raw fields are normalized into the shared schema automatically
- Max run seconds - wall-clock budget for the run (default 240). Cities are fetched one after another; when the budget is reached the Actor stops cleanly, finishes successfully with the permits it already has, names the cities it did not reach, and records
stoppedEarlyOnTimeLimit: truein the run'sSUMMARY. Raise it, together with the run timeout, for a deliberately large pull
Results land in the run's dataset, exportable as CSV, JSON, Excel, or via the Apify API.
Example use cases
- Roofing / solar / HVAC lead gen - keyword-filter for
roof,solar,HVAC, orre-roofacross your target cities and pull fresh permits with addresses to build a call list. - Contractor competitive tracking - pull permits that name a contractor, then filter the dataset on a competitor's
contractorNameto see where and what they're building. - Material supplier timing - filter by valuation to surface large new-construction projects the moment they're filed, then reach out before the concrete order is placed.
- Real-estate / proptech enrichment - use
latitude/longitudeandaddressto join permit activity onto your property database. - Market research - pull all cities over a date range to measure construction volume and mix by
permitTypeandvaluation.
Recurring use / scheduling
Set up an Apify Schedule (for example, a daily or weekly cron) so the actor re-runs on its own and captures newly filed and newly issued permits without manual effort - ideal for monitoring new building permits in a sales territory.
For clean, no-duplicate feeds:
- Use the date-range filter to only pull records since your last run.
- Point runs at the same named dataset and dedupe downstream on
permitId+sourceCity(unique per city). - Wire an integration (webhook, Google Sheets, Slack, or your CRM) to push each new batch straight into your workflow.
Optional: check a final reporting CSV
If you turn these results into a daily or weekly report, check the final transformed CSV separately from the Actor run. First inspect SUMMARY.failedSources, stoppedEarlyOnTimeLimit and stoppedOnChargeLimit; do not present a partial collection as complete.
For a synthetic or sanitized summary without names or addresses, group collected rows by sourceCity and count them. Your workflow could produce source_city,permit_rows,report_generated_at: these are derived summary columns, not this Actor’s native output. A generation timestamp records when you made that summary; it does not establish fresh permits. Do not use issueDate as report-generation time.
Try the free browser CSV checker with required summary headers and a deliberate row range. Allow zero rows when a valid empty result is expected. A header/row check does not validate the permit count’s accuracy or source completeness.
The final-export workflow guide explains optional recurring checks. Report Watch accepts up to 1 MiB, 100 columns and 10,000 data rows. Monitoring needs separate paid setup and a configured HTTP submission; it is not built into this Actor. Keep Apify’s native monitoring if it already covers your needs.
FAQ
How do I get building permit data for construction leads?
Run this actor against the cities you sell into, optionally filter by keyword, valuation, or date, and export the dataset to CSV or push it to your CRM. Each row includes the address, permit type, dates, and - where the city publishes it - the contractor and applicant, which is exactly the contact-and-context data lead-gen teams need.
Which US cities publish building permits as open data?
This actor covers 10 official portals: Chicago, San Francisco, New York City (DOB NOW), Austin, Seattle, Los Angeles, Baton Rouge, Cincinnati, Mesa, and Marin County. All are public Socrata open-data sources.
How can I scrape building permits from multiple cities into one format?
That is the core feature. Select multiple cities in one run and the actor maps each portal's differently-named columns into the same normalized schema, so every record shares the same fields regardless of source city.
How do I find new construction and renovation permits daily?
Schedule the actor to run daily and filter by issue date so each run returns recent records. Combine with a keyword like new or addition to focus on new construction and renovations.
Can I get building permit data with contractor and applicant names?
Where the source city publishes them, yes - the output includes contractorName and applicantName. Coverage of these fields varies by city; portals that expose them are mapped through, and those that don't are left blank rather than guessed.
What is the best building permits API for contractors?
For contractors who want a wide, normalized feed across many cities without managing a different integration per portal, this actor works as a pay-per-result building permits API: one input schema, one output schema, 10 cities, filterable by minimum valuation, keyword, contractor presence, and issue date.
How do I export building permit data to CSV or Excel?
Results go to the run's Apify dataset, which exports to CSV, Excel, JSON, or XML with one click, or via the Apify API for automated pipelines.
How do I monitor new building permits in my sales territory?
Pick the cities in your territory, set a schedule, filter by date range so each run is incremental, and route the output to Google Sheets, a webhook, or your CRM. Dedupe on permitId + sourceCity to keep the feed clean.
Is building permit data free and legal to scrape?
The underlying records come from official municipal open-data portals published for public use. This actor reads those public datasets; you are responsible for complying with each portal's terms and any applicable usage rules.
How do roofers, solar, and HVAC companies find permit leads?
They keyword-filter permit descriptions for terms like roof, solar, PV, or HVAC, restrict to their service-area cities and a recent date range, and pull the resulting addresses as a fresh lead list - then schedule it to repeat.
How do I filter building permits by valuation or project cost?
Use the minimum job valuation input to focus on large projects; it also drops permits whose city published no valuation. There is no maximum input - to target small jobs or a size band, filter the exported dataset on valuation.
Data source & notes
- Source: 10 official US city Socrata open-data portals - Chicago, San Francisco, New York City (DOB NOW), Austin, Seattle, Los Angeles, Baton Rouge, Cincinnati, Mesa, and Marin County.
- Public data: all records originate from public municipal open-data datasets. Respect each portal's terms of use.
- Field coverage varies by city.
contractorName,applicantName, andvaluationare populated where the source city publishes them; the actor never fabricates values. - Coverage: the 10 listed cities only - this actor does not cover every US municipality, and permit freshness depends on how often each city updates its open-data portal.
Related actors
Part of a set of US public-records tools that work well together:
- New Business Leads Scraper - newly registered businesses in the same metros - the other half of a local prospecting list
- Restaurant Inspection Data Scraper - the same city open-data approach applied to food-service inspections
See the full collection at apify.com/maydit.
Free guide: Turning building permit open data into contractor leads - the undocumented traps in this data source, measured against the live API.
Found this useful?
If this actor saved you time, a short review on the Apify Store genuinely helps. Reviews are how the next person decides whether a tool is worth trying.
Something broken, missing a field, or a source you want covered? Open an issue on the Issues tab and it will get looked at - that is the fastest route to getting it changed.
Run spending limits
The run stops at its spending limit. SUMMARY.datasetItemsSaved reports the number of rows actually saved, and SUMMARY.stoppedOnChargeLimit identifies this stop. A final batch may be saved only in part; increase the spending limit to collect more results.
Marin County identity: when the published permit number is blank, permitId uses the portal's published unique_id or permit_tracking_id. This identifies the source record; it does not assert that an unnumbered application has been issued.
Help with your run
Open the Issues tab on this Actor with the run URL, the input field that caused trouble and what you expected to receive. Remove API keys and private information before posting.
Understand your run
Open Run report in the run’s Output tab for saved-record counts, reported source issues and limits, and suggested next steps. Use CSV export to take the saved results into a spreadsheet. The existing JSON results and detailed machine-readable summary remain available.
The report reflects this run’s recorded coverage. A successful run or a saved result does not establish that every possible source record was collected.