Building Permits Scraper - Multi-City Construction Leads avatar

Building Permits Scraper - Multi-City Construction Leads

Pricing

from $1.50 / 1,000 results

Go to Apify Store
Building Permits Scraper - Multi-City Construction Leads

Building Permits Scraper - Multi-City Construction Leads

Building permits from dozens of city open-data portals in one run. Cities are discovered from the Socrata catalog, not a hand-kept list. Personal contact fields are dropped at the server.

Pricing

from $1.50 / 1,000 results

Rating

0.0

(0)

Developer

ABDULWAHAB NASER RASHED ALQARAWI

ABDULWAHAB NASER RASHED ALQARAWI

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Share

Building Permits — Multi-City Construction Leads

Building permits from dozens of city open-data portals in a single run.

Cities are discovered, not hard-coded. Every competing Actor on this data is wired to a fixed list somebody maintains by hand. This one queries the Socrata open-data catalog, reads each dataset's own field list, and builds the request from what that city actually publishes. A new city appears in the catalog and it is covered without a code change.


Personal data is dropped at the server

Raw permit payloads carry real people. Chicago's has ten contact columns including contact_1_name; Calgary has applicantname.

Filtering those after download is not filtering — the data still travelled, still sat in a dataset, still leaks on a crash. So every request sends an explicit $select of the safe columns only, and the server never emits the rest.

Verified on a 1,800-row run across six cities: zero personal fields present.


What you get

One row per permit, normalised across cities that name everything differently.

FieldCoverage
address99%
permitType97%
description93%
declaredValue73%
issuedAt66%
city31%
contractor22%

Plus source, dataset, permitNumber, status, appliedAt, completedAt, fee, state, postcode, latitude, longitude, scrapedAt — and raw, which keeps every extra column that city publishes so a buyer who needs a local field still has it.

Newest first. Without an explicit sort these portals return insertion order, which hands back permits from 2006 — worthless as construction leads. Results are ordered by issue date descending wherever the city publishes one, with the portal's row id as a tie-break so paging never repeats or skips a permit that shares its issue date with others.

Every value has its declared type. Portals publish location, link and checkbox columns as objects and booleans; a text field gets a string or null, a number field a finite number or null — never an object, NaN or Infinity.


Input

OptionDefaultWhat it does
querybuilding permitsSearched against the Socrata catalog to find cities
maxCities8City portals per run
maxPermitsPerCity500Permits per city
issuedSinceemptyYYYY-MM-DD. Anything else fails the run immediately with a clear message, instead of every city rejecting the filter
requestDelayMs300Politeness toward city servers
onlyNewfalseReturn only permits not delivered by an earlier run
stateStoreNamepermits-stateNamed key-value store that remembers delivered permits for onlyNew
sourcesempty (all)Only these cities, by dataset domain (e.g. data.cityofchicago.org)
permitTypesempty (all)Only permits whose permitType contains one of these words, case-insensitive
minDeclaredValueempty (none)Only permits with declaredValue at least this much

Choosing cities and filtering permits

sources picks cities by their dataset domain — the same value as each row's source and each coverage entry in the run report, and stable across runs. A pasted link is reduced to its domain; anything that is not a domain fails the run at once. Only cities that the catalog returns for your query can be matched (the catalog is asked for its first 100 datasets); a requested domain it did not return is listed under sourcesNotFound in the run report and in the status message, never silently dropped. maxCities still applies.

permitTypes and minDeclaredValue are checked on each permit before it is delivered, so a filtered-out permit is never charged, and with onlyNew it is not remembered as delivered. A permit with no permitType never matches a type filter, and one with no declaredValue never passes a minimum above 0 — an unknown value is not treated as big enough. The filters are applied to the permits read, and maxPermitsPerCity still bounds how many are read, so a strict filter can return fewer permits than that limit. Values are in each city's own currency (Calgary and Edmonton publish Canadian dollars). The run report counts filteredOut overall and per city.

Only new permits (onlyNew)

Schedule the Actor daily with onlyNew on and each run returns only permits you have not received before — you are not charged twice for the same lead.

  • Each delivered permit is remembered by its permit number (or, where a city publishes none, a hash of its source, issue date, type, address and description), per city dataset, in a named key-value store in your account.
  • Up to the last 50,000 permits per city are remembered.
  • A permit is remembered only after it was actually delivered, so a run stopped by your spending limit never hides a permit you did not get.
  • maxPermitsPerCity then counts permits checked (newest first), not permits returned — a quiet day returns few or none.

Measured locally, 14 Sep 2026, 2 cities × 5 permits: first run 10 permits, second run minutes later 0 permits.


Use it for

  • Construction leads — filter declaredValue, sort by issuedAt
  • Contractor prospecting — who is pulling permits, and for what size of work
  • Market research — permit volume and declared value by city over time
  • Supplier targeting — match permitType to what you sell

Speed and cost

Measured locally, 14 Sep 2026: 15 permits from 3 cities (Chicago, Calgary, Seattle) in 12.5 seconds, 4 requests — a deliberately small run. Each city costs one request per 1,000 permits.

On 14 Sep 2026 the catalog offered 42 city datasets; 40 answered a request.


Honest notes

Coverage is uneven by design. city sits at 31% and contractor at 22% because many portals simply do not publish those columns. They come back null rather than the row changing shape — check the field you need before buying at scale.

Some portals stop answering. They are city IT departments, not APIs with an SLA. Unreachable cities are listed in the run report under skipped rather than failing the run.

Dates vary in format between portals; they are passed through as the city publishes them rather than being guessed into a single format.

Every run publishes a report to the key-value store under RUN_REPORT: cities covered, cities skipped and why, fields kept per city, and cost per 1,000. The run's status message always summarises it, e.g. 15 permit(s) from 3 cities; skipped: ....


Questions or a city that will not load?

Open an issue with the portal domain.