# US Building Permits API - Normalized Construction Leads (`webdata_labs/us-building-permits-api`) Actor

\[💵 $2.00 / 1K] One normalized schema for US building permits across major cities (Austin, Chicago, San Francisco, NYC). Unified permit type, status, valuation, geocoded address, dates, and contractor/owner contact - not a raw per-city dump.

- **URL**: https://apify.com/webdata\_labs/us-building-permits-api.md
- **Developed by:** [WebData Labs](https://apify.com/webdata_labs) (community)
- **Categories:** Lead generation, Real estate, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 permit records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## US Building Permits API - Normalized Construction Leads

**One clean schema for US building permits across major cities.** Pick a city, filter by issue date, permit type, valuation, or keyword, and get analysis-ready permit rows: normalized permit category, status, construction valuation, geocoded address, key dates, and contractor / owner contact - including phone numbers where the city publishes them.

Every US city posts building permits on its own open-data portal, and every portal has a different schema. Chicago names contractors in `contact_1_name` and reports cost in `reported_cost`; New York City buries the licensed contractor in `permittee_s_business_name` with a phone in `permittee_s_phone__` and stores dates as text; San Francisco uses `estimated_cost` and a GeoJSON point; Austin splits out `contractor_company_name`, `contractor_phone`, and `contractor_trade`. Most "permit scrapers" hand you one city's raw columns. This Actor does the hard part: it maps each city onto **one unified schema**, normalizes dates to ISO, coerces valuation to a number, classifies the permit into a cross-city category, composes a single clean address, and pulls contractor/owner contacts into the same fields every time.

### ✅ What you get / ❌ what this isn't

| This Actor gives you | This Actor is not |
|---|---|
| One normalized row per permit, identical shape across every city | Not a raw per-city column dump |
| Cross-city `permitCategory` (SOLAR, ROOFING, ELECTRICAL, NEW\_CONSTRUCTION...) | Not affiliated with or endorsed by any city or government |
| Contractor name, trade, license, and phone where the city publishes it | Not a guarantee every city exposes contractor or valuation data |
| Construction `valuation` coerced to a number, dates normalized to ISO | Not real-time - reflects each portal's publishing cadence |
| Geocoded address (street, locality, region, postal, lat/lng) | Not a credit, licensing, or legal-status check on any contractor |
| Reliable official open-data reads (no anti-bot, no proxy needed) | Not a national database - supported cities are listed below |

### 🔎 Why use this Actor

- Build fresh construction lead lists - solar, roofing, remodeling, HVAC - filtered by city, date, and trade.
- Monitor new permits weekly for a sales territory without learning four different city APIs.
- Track high-value projects by filtering on minimum construction valuation.
- Feed one consistent permit schema into a CRM, dashboard, model, or LLM pipeline.
- Skip the plumbing - date parsing, valuation coercion, address composition, and contact extraction are done.

### 👥 Who it's for

- Contractors and trade businesses (solar, roofing, HVAC, remodeling) buying local permit leads.
- Building-material suppliers and manufacturers tracking new construction activity.
- Proptech, construction-tech, and market-research teams needing normalized permit data.
- Sales and go-to-market teams building territory lead lists.
- Data teams that want one schema instead of a per-city ETL project.

### 🗂️ What data you get

One row per permit:

| Field | Type | Description |
|---|---|---|
| `source`, `city`, `state` | string | Which city portal the row came from |
| `permitNumber`, `permitUrl` | string | City permit identifier and its detail page (where available) |
| `permitType` | string | The city's raw permit-type label |
| `permitCategory` | string | Normalized cross-city category (SOLAR, ROOFING, ELECTRICAL, PLUMBING, MECHANICAL\_HVAC, NEW\_CONSTRUCTION, ADDITION\_ALTERATION, DEMOLITION, SIGN, POOL\_SPA, FENCE\_WALL, DRIVEWAY\_SITE, OTHER) |
| `workClass`, `description` | string | Secondary work classification and work description |
| `status`, `statusNormalized` | string | Raw status and normalized status (ISSUED, COMPLETED, IN\_PROCESS, INACTIVE) |
| `appliedDate`, `issuedDate`, `expirationDate`, `completedDate` | string | Key dates, normalized to `YYYY-MM-DD` |
| `valuation`, `valuationType` | number / string | Construction value coerced to a number, and which field it came from |
| `address`, `street`, `locality`, `region`, `postalCode` | string | Composed address plus components |
| `latitude`, `longitude` | number | Geocoordinates where published |
| `contractorName`, `contractorTrade`, `contractorLicense`, `contractorPhone`, `contractorLocation` | string | Contractor contact where the city publishes it |
| `ownerName`, `ownerBusinessName`, `applicantName` | string | Owner / applicant where published |
| `contacts` | array | All parties on the permit, each with role, name, and (where present) phone / license |

### Example tasks

- [Fresh solar install leads in Austin](https://apify.com/webdata_labs/us-building-permits-api/examples/fresh-solar-install-leads-in-austin)
- [High-value construction permits in San Francisco](https://apify.com/webdata_labs/us-building-permits-api/examples/high-value-construction-permits-in-san-francisco)
- [New building permits with contractor contacts in NYC](https://apify.com/webdata_labs/us-building-permits-api/examples/new-building-permits-with-contractor-contacts-in-nyc)

### 🌎 Supported cities

| City | Source portal | Contractor data | Valuation |
|---|---|---|---|
| Austin, TX | data.austintexas.gov | Name, trade, phone | - |
| Chicago, IL | data.cityofchicago.org | Typed contacts (name, location) | Reported cost |
| San Francisco, CA | data.sfgov.org | - | Estimated cost |
| New York City, NY | data.cityofnewyork.us | Permittee business, phone, license | - |

More cities are added over time. Request a city via an Actor issue.

### ⚙️ How to get building permit data

1. Open the Actor on Apify.
2. Choose a `city`.
3. Optionally filter by `issuedAfter` / `issuedBefore`, `permitTypeContains`, `minValuation`, or `searchText`.
4. Set how many permits to return (`maxItems`).
5. Run the Actor.
6. Open the `Permits` dataset view.
7. Export JSON, CSV, Excel, HTML, or XML, or call the Actor through the Apify API.

### 📥 Input

```json
{
  "city": "austin",
  "searchText": "solar",
  "issuedAfter": "2026-01-01",
  "maxItems": 500
}
```

### 📤 Output

```json
{
  "recordType": "permit",
  "source": "austin",
  "city": "Austin",
  "state": "TX",
  "permitNumber": "2026-064893 EP",
  "permitType": "Electrical Permit",
  "permitCategory": "SOLAR",
  "status": "Active",
  "statusNormalized": "ISSUED",
  "issuedDate": "2026-06-26",
  "valuation": null,
  "address": "715 E 32ND ST, AUSTIN, TX 78705",
  "latitude": 30.29,
  "longitude": -97.72,
  "contractorName": "Freedom Solar Power",
  "contractorTrade": "Electrical Contractor",
  "contractorPhone": "5125967031",
  "contacts": [
    {"role": "contractor", "name": "Freedom Solar Power", "trade": "Electrical Contractor", "phone": "5125967031"}
  ]
}
```

### 💵 How much does it cost?

The launch price is about `$2.00 / 1,000 permits`, tier-discounted for higher Apify plans. One permit row is one charged result. A run returning 500 permits is 500 results. Error rows are not charged.

### 🔁 Run it on the Apify platform

Schedule a weekly run per city to keep a fresh lead feed, call it from the Apify API, export to CSV/JSON/Excel, or connect the dataset to Make, Zapier, webhooks, a warehouse, a CRM, or an LLM pipeline.

### ⚠️ Limits and caveats

- This Actor reads each city's **public open-data portal**. It is not affiliated with any city or government, and it does not check a contractor's license validity, credit, or legal status.
- **Field coverage varies by city.** Not every city publishes contractor contact, phone, or valuation; missing fields are returned as `null` rather than guessed. See the supported-cities table.
- **NYC ordering caveat.** NYC stores `issuance_date` as unsortable text, so results are ordered (and `issuedAfter` / `issuedBefore` filtered) on the DOB processing date `dobrundate`. The permit's own issuance date is still parsed into `issuedDate`.
- **`permitCategory` is best-effort** keyword classification over each city's raw type/description vocabulary; the raw `permitType` is always preserved.
- Data reflects each portal's publishing cadence, which can lag the permit office by days.

### 🧩 Related Actors

- Website Contact Extractor - emails, phones, and socials from any domain.
- Lead List Deduplicator - dedupe and normalize messy lead lists.
- Shopify Store Analyzer - catalog and contacts from any Shopify store.
- SEC Financials API - normalized income, balance sheet, and cash flow from EDGAR.

### ❓ FAQ

#### Which cities are supported?

Austin, Chicago, San Francisco, and New York City at launch. Each is sourced from that city's official open-data portal and normalized to the same schema. More cities are added over time.

#### Where does the data come from?

Each city's public open-data portal (Socrata). These are the same datasets the cities publish for free; this Actor's value is normalizing them into one consistent, lead-ready schema.

#### Which cities include contractor phone numbers?

Austin and NYC publish a contractor/permittee phone on most records. Chicago publishes typed contacts (name and location, no phone). San Francisco does not publish contractor contact. The `contractorPhone` field is populated wherever the city provides it.

#### Why are some fields null?

Because that city does not publish that field for that permit. Coverage differs by city and by record type; nothing is guessed.

#### Does it need a proxy?

No. City open-data portals are public and served reliably to datacenter IPs. Enable Apify Proxy only for very large batches.

### 🛠️ Support

For bugs, missing fields, or a city request, open an Actor issue with the run URL, the city and filters used, and the field or behavior you expected.

### ⭐ Rate this Actor

If this Actor saved you time, please take 30 seconds to leave a review on the **Reviews** tab of [US Building Permits API - Normalized Construction Leads](https://apify.com/webdata_labs/us-building-permits-api) - reviews are the main trust signal other users see, and they directly decide which features get built next. If something is broken or a field is missing, please [open an issue](https://apify.com/webdata_labs/us-building-permits-api/issues) first - we typically respond within a day and would love the chance to fix it before you rate.

# Actor input Schema

## `city` (type: `string`):

Which city's permits to pull. Each city is sourced from its official open-data portal and normalized to the same schema.

## `issuedAfter` (type: `string`):

Only permits issued on/after this date (YYYY-MM-DD). For NYC this filters on the DOB processing date (see README).

## `issuedBefore` (type: `string`):

Only permits issued on/before this date (YYYY-MM-DD).

## `permitTypeContains` (type: `string`):

Case-insensitive substring match on the city's raw permit-type field (e.g. 'electrical', 'sign', 'new construction'). Use permitCategory in the output for a normalized cross-city category.

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

Only permits whose reported/estimated construction value is at least this amount. Applies only to cities that publish a valuation (Chicago, San Francisco); ignored for others.

## `searchText` (type: `string`):

Optional Socrata full-text search across the whole record (work description, names, etc.).

## `maxItems` (type: `integer`):

Maximum number of permits to return. Newest first (by the city's issue/processing date).

## `includeRaw` (type: `boolean`):

Attach the city's original unnormalized record under 'raw' for auditing. Off by default to keep rows clean.

## `socrataAppToken` (type: `string`):

Optional free Socrata app token to raise rate limits for very large pulls. Not required for normal use.

## `proxyConfiguration` (type: `object`):

Optional. City open-data portals are public and work without a proxy; enable Apify Proxy only for very large batches.

## Actor input object example

```json
{
  "city": "austin",
  "issuedAfter": "2026-01-01",
  "maxItems": 500,
  "includeRaw": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `OUTPUT` (type: `string`):

No description

# 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 = {
    "city": "austin"
};

// Run the Actor and wait for it to finish
const run = await client.actor("webdata_labs/us-building-permits-api").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 = { "city": "austin" }

# Run the Actor and wait for it to finish
run = client.actor("webdata_labs/us-building-permits-api").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 '{
  "city": "austin"
}' |
apify call webdata_labs/us-building-permits-api --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/0Twa2ancta1oIy1ud/builds/Z5uphXXdeNP14pjfA/openapi.json
