# US Building Permits Scraper - 10 Cities, One Schema (`maydit/us-building-permits-scraper`) Actor

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.

- **URL**: https://apify.com/maydit/us-building-permits-scraper.md
- **Developed by:** [Brandt May](https://apify.com/maydit) (community)
- **Categories:** Lead generation, Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.80 / 1,000 results

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 Scraper - 10 Cities in One Schema

> 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, project value, keyword, contractor, and 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 |
|---|---|
| `permitNumber` | Official permit identifier from the source city |
| `permitType` | Type/category of permit (new build, alteration, etc.) |
| `status` | Current permit status |
| `description` | Work description / scope text |
| `address` | Street address of the permitted work |
| `city` | City the address is in |
| `state` | US state |
| `zip` | ZIP / postal code |
| `valuation` / `estimatedCost` | Declared project value or estimated cost |
| `contractorName` | Contractor on the permit (where the city publishes it) |
| `applicant` | Applicant / filer on the permit |
| `issuedDate` | Date the permit was issued |
| `filedDate` | 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 |
| `permitUrl` | Link back to the record on the source portal |

> Note: not every city publishes every field. `contractorName`, `applicant`, and `valuation`/`estimatedCost` availability 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
- **Valuation min / max** - keep only projects above or below a dollar threshold
- **Keyword** - match against the permit description (e.g. `roof`, `solar`, `remodel`)
- **Contractor name** - filter to permits tied to a specific contractor
- **Date range** - restrict by filed or issued date
- **Multi-city pull** - fetch several cities in a single run; each city's raw fields are normalized into the shared schema automatically

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`, or `re-roof` across your target cities and pull fresh permits with addresses to build a call list.
- **Contractor competitive tracking** - filter by a competitor's `contractorName` to 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`/`longitude` and `address` to join permit activity onto your property database.
- **Market research** - pull all cities over a date range to measure construction volume and mix by `permitType` and `valuation`.

### 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 `permitNumber` + `sourceCity` (unique per city).
- Wire an **integration** (webhook, Google Sheets, Slack, or your CRM) to push each new batch straight into your workflow.

### 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 filed or issued date so each run only 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 `applicant`. 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 valuation, keyword, contractor, and 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 `permitNumber` + `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 valuation min and max inputs. Set a minimum to focus on large projects, a maximum to focus on small jobs, or both to target a specific project-size band.

### 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`, `applicant`, and `valuation`/`estimatedCost` are only 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](https://apify.com/maydit/us-business-licenses-scraper) - newly registered businesses in the same metros - the other half of a local prospecting list
- [Restaurant Inspection Data Scraper](https://apify.com/maydit/us-restaurant-inspections-scraper) - the same city open-data approach applied to food-service inspections

See all fifteen at [apify.com/maydit](https://apify.com/maydit).

**Free guide:** [Turning building permit open data into contractor leads](https://mayd-it.com/data-tools/guides/building-permit-data-roofing-solar-hvac-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.

# Actor input Schema

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

Which cities to scrape. Leave empty to scrape all supported cities.

## `issuedSince` (type: `string`):

Only permits issued on or after this date (YYYY-MM-DD). Use this for recurring/monitoring runs, e.g. last 7 days.

## `issuedUntil` (type: `string`):

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

## `permitTypeKeywords` (type: `array`):

Only keep permits whose type/description/class contains one of these keywords (case-insensitive). E.g. 'solar', 'roof', 'pool', 'demolition'. Leave empty for all.

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

Only keep permits with a reported job valuation at or above this amount. Applied server-side for cities that publish valuation (Chicago, San Francisco, Austin, Seattle). New York does not publish job cost.

## `onlyWithContractor` (type: `boolean`):

Keep only records that include a contractor/company name (best for lead generation). Note: San Francisco does not publish contractor names.

## `maxResultsPerCity` (type: `integer`):

Upper bound on permits returned per city per run.

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

Attach the full original source record to each result under 'raw'. Increases output size.

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

Optional Socrata app token to raise API rate limits on large runs. Free to obtain from any Socrata portal. Not required for normal use.

## Actor input object example

```json
{
  "cities": [
    "chicago",
    "san_francisco",
    "new_york",
    "austin",
    "seattle",
    "los_angeles",
    "baton_rouge",
    "cincinnati",
    "mesa",
    "marin_county"
  ],
  "issuedSince": "2026-06-01",
  "permitTypeKeywords": [],
  "onlyWithContractor": false,
  "maxResultsPerCity": 1000,
  "includeRaw": false
}
```

# 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 = {};

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

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

```

## MCP server setup

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

```

## OpenAPI specification

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