# Us Building Permit Monitor (`jamkon/us-building-permit-monitor`) Actor

Monitor newly issued US building permits (NYC, Chicago, SF, Austin) by trade - roofing, solar, HVAC, plumbing and more. Deduped daily feed, official city open data, no owner personal data.

- **URL**: https://apify.com/jamkon/us-building-permit-monitor.md
- **Developed by:** [james correy](https://apify.com/jamkon) (community)
- **Categories:** Automation, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 new permits

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## New Building Permit Monitor - Deduped Daily Contractor Leads (US)

Get **newly issued building permits** in major US cities as a clean, deduplicated feed — roofing, solar, HVAC, plumbing, electrical, pool, demolition and more. Run it on a schedule and receive **only the permits that are new since your last run**, never the whole pile again.

Built on **official city open-data portals** (NYC, Chicago, San Francisco, Austin). No scraping, no fragile page automation, and **no owner personal data**.

### Who uses this

- **Material suppliers, subcontractors, and service businesses**: a new permit is a project about to start and a buyer about to spend. Reach out first.
- **Solar / roofing / HVAC sales teams**: filter to your exact trade and city and get a daily list of fresh jobs.
- **Proptech and market analysts**: track construction activity by city, trade and value.

### Why "deduped monitor" matters

Most permit datasets dump the entire history every time. This actor remembers where it got to and emits **only new permits** on each run — so a daily schedule gives you a clean daily lead list, ready for your CRM or a webhook, with no duplicates to filter out.

The **first run emits a starter batch**: permits issued in the last few days (3 by default, set with **Starter batch days**), so you get real leads immediately. From then on, each run emits only permits that are new since your last run. Schedule it daily.

### What you get

```json
{
  "cityLabel": "Chicago",
  "permitNumber": "100987654",
  "permitType": "PERMIT - NEW CONSTRUCTION",
  "normalizedTrade": "general_building",
  "valuation": 425000,
  "siteAddress": "1234 N Damen Ave",
  "zip": null,
  "issueDate": "2026-07-04T00:00:00.000",
  "contractorBusinessName": null,
  "contractorLicenseNumber": null,
  "latitude": 41.90,
  "longitude": -87.67
}
```

Filter by **trade**, **city**, and **minimum valuation**. Point it at a **webhook** to push straight into Zapier/Make/n8n or your CRM.

### What this actor never collects

Permit records often contain the owner's name, home address, and the permittee's personal phone number. This actor emits **the permit, the work, the value, the site address, and the contractor's BUSINESS identity only**:

- No owner personal names
- No owner home addresses (separate from the job site)
- No personal phone numbers
- Contractor fields are business name and license number only, and only where the city publishes them as business data (currently New York City)

### Coverage

| City | Source | Valuation | Contractor |
|---|---|---|---|
| New York City | NYC DOB permit issuance | – | business name + license |
| Chicago | Chicago building permits | yes | – |
| San Francisco | SF building permits | yes | – |
| Austin | Austin issued construction permits | – | – |

Need another city? Open an issue and name it — most US cities with a Socrata/open-data portal can be added quickly.

### Notes

- Cities report on their own schedules; a permit may appear a day or two after issuance. The monitor handles late-arriving records by re-checking the boundary day each run.
- Trades are classified from each city's permit-type and work-description text; use the `normalizedTrade` filter for consistent cross-city trades.
- Found a problem or need a city or field added? Open an issue — replies are fast.

# Actor input Schema

## `cities` (type: `array`):

Which cities to monitor. More cities added on request.

## `trades` (type: `array`):

Only emit permits for these trades. Leave empty for all.

## `minValuation` (type: `integer`):

Only emit permits with a reported value at or above this (permits with no value are excluded when set). Cities without a value field: NYC and Austin.

## `webhookUrl` (type: `string`):

If set, each run POSTs a summary to this URL (results are always in the dataset too).

## `seedLookbackDays` (type: `integer`):

On the very first run for a city, emit permits from this many days back as a starter batch, then track only new permits after that. Default 3.

## Actor input object example

```json
{
  "cities": [
    "nyc",
    "chicago",
    "sf",
    "austin"
  ],
  "trades": [],
  "seedLookbackDays": 3
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "cities": [
        "nyc",
        "chicago",
        "sf",
        "austin"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("jamkon/us-building-permit-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "cities": [
        "nyc",
        "chicago",
        "sf",
        "austin",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("jamkon/us-building-permit-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "cities": [
    "nyc",
    "chicago",
    "sf",
    "austin"
  ]
}' |
apify call jamkon/us-building-permit-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=jamkon/us-building-permit-monitor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/zaUW8NtCZydWQMs5J/builds/Cj8pYoABlkaevpsGu/openapi.json
