Make + Apify · Permits and property
Building Permits to Google Sheets with Make
The Building Permits Scraper reads 61 US city, county and state open-data portals and, in monitor mode, returns only permits it has not returned before. Save it as an Apify task, schedule it daily, and a three-module Make scenario built on Apify's official Make app adds each new permit to a Google Sheet: a lead list for contractors and suppliers that fills itself.
Building Permits Scraper — Roofing & Construction Leads. Pay per result; see the Store page for current pricing.
What you build
A daily Apify schedule runs a saved task that pulls roofing permits issued in Austin, Seattle and Denver over the last 7 days. When the run finishes, Make's Watch Task Runs trigger starts the scenario, Get Dataset Items reads the run's permits, and Google Sheets gets one row per new permit with the address, the work description, the declared cost and the contractor where the city publishes one.
Change jurisdictions and permitTypes for your market: solar, pool, hvac or demolition work the same way. The building permits guide lists all 61 jurisdictions; cities on Accela or EnerGov portals use the Accela and EnerGov scraper, which has the same schema and works with this scenario.
Before you start
- An Apify account. The Actor is billed per result to that account; the Store page lists the current prices. Set a maximum total charge in the task's run options to cap a run.
- A Make account with a Google connection.
- A Google Sheet with a header row, for example:
issuedDate,jurisdictionName,permitNumber,permitType,workDescription,address,city,zip,estimatedCost,contractorName,contractorPhone,sourceUrl.
Step 1: Save the input as an Apify task
Open the Actor in Apify Console from its Store page. On the Input tab, switch to the JSON editor, paste this input, set your own jurisdictions and permit words, and click Save as a new task:
{
"jurisdictions": [
"austin",
"seattle",
"denver-residential"
],
"permitTypes": [
"roof",
"re-roof"
],
"issuedWithinDays": 7,
"maxResultsPerJurisdiction": 500,
"onlyNewSinceLastRun": true,
"stateStoreName": "make-sheets-roof-permits",
"includeRaw": false
}
With onlyNewSinceLastRun each run returns only permits that earlier runs of this task have not returned (flagged isNew: true), so the sheet gets no duplicates. The first run returns everything issued in the window. A 7-day window on a daily schedule also catches portals that publish a few days late. Run the task once from Console now, so Make has a run to map fields from.
Then open Schedules in Console, create a daily schedule, and add the task to it.
Step 2: Build the Make scenario
1. Trigger: Apify, Watch Task Runs
Create a scenario and add the Apify app's Watch Task Runs trigger. Create a connection (OAuth, or paste an API token from Console → Settings → API & Integrations), then pick the task. The trigger registers a webhook in Apify that fires whenever a run of the task finishes.
2. Search: Apify, Get Dataset Items
Add Apify → Get Dataset Items and map Dataset ID to the default dataset ID from the trigger's output. If the variables do not show yet, run the scenario once while the task runs, then map them.
3. Filter out error items
On the link between Get Dataset Items and the next module, set up a filter: continue only if error does not exist. A portal that is down produces one error item, such as HTTP_503, instead of failing the run.
4. Action: Google Sheets, Add a Row
Add Google Sheets → Add a Row, pick the spreadsheet and sheet, and map each column to a permit field. Get Dataset Items outputs one bundle per permit, so the module adds one row per permit. (Apify's own Make guide uses Bulk Add Rows with an aggregator instead, which uses fewer operations on large runs.) Save the scenario and switch it on.
Fields to map
Each dataset item is one permit. Fields that make a useful lead row:
| Field | Use it for |
|---|---|
issuedDate, appliedDate | Dates as the portal publishes them |
jurisdictionName, permitNumber | Where the permit was issued and its number |
permitType, permitSubtype, workDescription | What the work is, in the city's own words |
address, city, state, zip | The job site |
estimatedCost | Declared job value, or empty where the city publishes none |
contractorName, contractorLicense, contractorPhone | Only where the city publishes them; nothing is inferred |
sourceUrl | Link to the source dataset or row, to check a value |
All fields are described in the Building permits API guide.
Costs and limits
- Apify bills the Actor per permit, per jurisdiction and per results page, at the prices on its Store page. In monitor mode you pay for new permits only after the first run.
- Make counts operations per module run; with one row per permit, a run with 100 new permits uses about 100 Google Sheets operations.
- Each city publishes its own columns: some have no cost or contractor columns, and update frequency ranges from daily to every few weeks. The building permits guide lists the gaps.
- If you contact people from the sheet, telemarketing and e-mail laws apply: the TCPA and the National Do Not Call Registry in the US, CASL in Canada.
- Not a consumer report. Not for employment, credit, insurance, housing or tenant-screening decisions.
FAQ
Can Make run the Actor itself instead of a task schedule?
Yes. Apify's Run an Actor module with Run synchronously set to Yes waits for the run, and Make's own scheduler can start the scenario. Apify's documentation warns that Make enforces a plan-dependent timeout on synchronous runs and that output is incomplete when a run exceeds it, so for many jurisdictions the task trigger is safer.
Why are some contractor columns empty?
The city does not publish them. Set includeRaw to true once to see every column a portal does publish.
Do I need API keys for the city portals?
No. They are public open-data APIs. A free Socrata app token is optional and only raises Socrata's rate limits.
Is this affiliated with Make or Google?
No. owlabee is an independent developer on Apify Store, and the Make app used here is Apify's own. Not affiliated with or endorsed by Make, Google, Apify or any city named.