# Building Permits Scraper - 47 US Cities, Construction Leads (`loomwise/city-building-permits`) Actor

New building permits from 47 US cities & counties (Chicago, NYC, LA, DC, Philadelphia, San Antonio, San Jose, Miami-Dade, all of NJ...) via official open data. One schema, contractor business names. Filter by state. $2/1k.

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

## Pricing

from $2.00 / 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.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Building Permits Scraper: construction leads from 47 US cities and counties (one schema, no API key)

Get **newly issued building permits** from the official open-data portals of **47 US cities and counties**, including Chicago, New York City, Los Angeles, San Francisco, Seattle, Austin, Boston, Philadelphia, Washington DC, Baltimore, San Antonio, San Jose, Pittsburgh, Nashville, Louisville, Columbus, Cleveland, Orlando, Miami-Dade County, San Diego County and the **whole state of New Jersey**. Use it as a **building permit API** for contractor and construction lead generation (roofing, solar, HVAC, remodeling, new construction). Every city comes back in **one clean, unified schema**: permit number, type, normalized work category, description, issue date, job valuation, project address, ZIP, coordinates, and the **contractor business name** where the city publishes one.

No scraping, no browser, no proxies. The Actor reads each city's public API (Socrata, ArcGIS REST, CKAN or Carto), so runs take seconds. A 7-day, 9-city pull (before the 2026-10 expansion) returns about 5,900 permits in about 4 seconds.

### Who uses this

- **Contractors, subcontractors and suppliers** looking for fresh project leads: new construction, roofing, solar, HVAC, electrical, demolition.
- **Building-material and equipment-rental sales teams** tracking where work is starting.
- **Proptech, insurance and lending analysts** monitoring renovation and new-construction activity by ZIP or neighborhood.
- **Market researchers and journalists** comparing construction activity and valuations across major US cities.

### Cities and sources (49 feeds, 47 cities and counties, 20 states + DC)

| Place | State | `cities` ID | Platform | Contractor business names | Source |
|---|---|---|---|---|---|
| Mesa | AZ | `mesa_az` | socrata | yes | [dataset](https://citydata.mesaaz.gov/d/dzpk-hxfb) |
| Anaheim | CA | `anaheim_ca` | arcgis | yes | [dataset](https://services3.arcgis.com/hPs600I3X0RTaaaq/arcgis/rest/services/Accela_Building_Permits/FeatureServer/0) |
| Citrus Heights | CA | `citrus_heights_ca` | arcgis | yes | [dataset](https://services8.arcgis.com/F2vUxnlx169smga0/arcgis/rest/services/BuildingPermitsIssued/FeatureServer/0) |
| Corona | CA | `corona_ca` | socrata | no | [dataset](https://corstat.coronaca.gov/d/2agx-camz) |
| Los Angeles | CA | `los_angeles` | socrata | no | [dataset](https://data.lacity.org/d/pi9x-tg5x) |
| Marin County | CA | `marin_county_ca` | socrata | yes | [dataset](https://data.marincounty.gov/d/mkbn-caye) |
| San Diego County (unincorporated) | CA | `san_diego_county_ca` | socrata | yes | [dataset](https://data.sandiegocounty.gov/d/red2-qccu) |
| San Francisco | CA | `san_francisco` | socrata | no | [dataset](https://data.sfgov.org/d/i98e-djp9) |
| San Jose (last 30 days feed) | CA | `san_jose_ca` | ckan | yes | [dataset](https://data.sanjoseca.gov/dataset/last-30-days-building-permits) |
| Boulder | CO | `boulder_co` | arcgis | yes | [dataset](https://services.arcgis.com/ePKBjXrBZ2vEEgWd/arcgis/rest/services/Construction_Permits/FeatureServer/0) |
| Washington, DC (last 30 days feed) | DC | `washington_dc` | arcgis | some | [dataset](https://maps2.dcgis.dc.gov/dcgis/rest/services/FEEDS/DCRA/FeatureServer/4) |
| Miami-Dade County (unincorporated) | FL | `miami_dade_fl` | arcgis | yes | [dataset](https://services.arcgis.com/8Pc9XBTAsYuxx9Ny/arcgis/rest/services/miamidade_permit_data/FeatureServer/0) |
| Orlando | FL | `orlando_fl` | socrata | yes | [dataset](https://data.cityoforlando.net/d/ryhf-m453) |
| Boise (high-impact permits) | ID | `boise_id` | arcgis | no | [dataset](https://services1.arcgis.com/WHM6qC35aMtyAAlN/arcgis/rest/services/PDS_BuildingPermits_HighImpact/FeatureServer/0) |
| Chicago | IL | `chicago` | socrata | yes | [dataset](https://data.cityofchicago.org/d/ydr8-5enu) |
| Overland Park | KS | `overland_park_ks` | arcgis | no | [dataset](https://services1.arcgis.com/YQsWDBr0DjMtoTQo/arcgis/rest/services/Building_Permits/FeatureServer/0) |
| Louisville Metro (active construction permits) | KY | `louisville_ky` | arcgis | some | [dataset](https://services1.arcgis.com/79kfd2K6fskCAkyg/arcgis/rest/services/active_construction_permits/FeatureServer/0) |
| Baton Rouge (East Baton Rouge Parish) | LA | `baton_rouge` | socrata | yes | [dataset](https://data.brla.gov/d/7fq7-8j7r) |
| New Orleans | LA | `new_orleans` | socrata | yes | [dataset](https://data.nola.gov/d/rcm3-fn58) |
| Boston | MA | `boston` | ckan | some | [dataset](https://data.boston.gov/dataset/approved-building-permits) |
| Cambridge, MA (additions/alterations) | MA | `cambridge_ma_alterations` | socrata | yes | [dataset](https://data.cambridgema.gov/d/qu2z-8suj) |
| Cambridge, MA (new construction) | MA | `cambridge_ma_new` | socrata | no | [dataset](https://data.cambridgema.gov/d/9qm7-wbdc) |
| Worcester | MA | `worcester_ma` | arcgis | some | [dataset](https://services1.arcgis.com/j8dqo2DJE7mVUBU1/arcgis/rest/services/Building_Permits/FeatureServer/0) |
| Baltimore | MD | `baltimore_md` | arcgis | no | [dataset](https://baltegis.baltimorecity.gov/mapping/rest/services/Housing/DHCD_Open_Baltimore_Datasets/FeatureServer/3) |
| Montgomery County, MD (commercial) | MD | `montgomery_county_md_commercial` | socrata | no | [dataset](https://data.montgomerycountymd.gov/d/i26v-w6bd) |
| Montgomery County, MD (residential) | MD | `montgomery_county_md_residential` | socrata | no | [dataset](https://data.montgomerycountymd.gov/d/m88u-pqki) |
| New Jersey (statewide, all municipalities) | NJ | `new_jersey` | socrata | n/a | [dataset](https://data.nj.gov/d/w9se-dmra) |
| New York City | NY | `nyc` | socrata | yes | [dataset](https://data.cityofnewyork.us/d/rbx6-tga4) |
| Cincinnati | OH | `cincinnati` | socrata | yes | [dataset](https://data.cincinnati-oh.gov/d/uhjb-xac9) |
| Cleveland | OH | `cleveland_oh` | arcgis | yes | [dataset](https://services3.arcgis.com/dty2kHktVXHrqO8i/arcgis/rest/services/Building_Permits/FeatureServer/0) |
| Columbus | OH | `columbus_oh` | arcgis | yes | [dataset](https://services1.arcgis.com/9yy6msODkIBzkUXU/arcgis/rest/services/Building_Permits/FeatureServer/0) |
| Delaware County (townships) | OH | `delaware_county_oh` | arcgis | yes | [dataset](https://services2.arcgis.com/ziXVKVy3BiopMCCU/arcgis/rest/services/Building_Permits_from_August_2025_to_July_2026/FeatureServer/0) |
| Philadelphia | PA | `philadelphia` | carto | yes | [dataset](https://opendataphilly.org/datasets/licenses-and-inspections-building-and-zoning-permits/) |
| Pittsburgh | PA | `pittsburgh_pa` | ckan | no | [dataset](https://data.wprdc.org/dataset/pli-permits) |
| Sumter | SC | `sumter_sc` | arcgis | no | [dataset](https://gis.sumter-sc.com/server/rest/services/Building/BuildingPermit/FeatureServer/0) |
| Nashville (Davidson County) | TN | `nashville_tn` | arcgis | yes | [dataset](https://services2.arcgis.com/HdTo6HJqh92wn4D8/arcgis/rest/services/Building_Permits_Issued_2/FeatureServer/0) |
| Austin | TX | `austin` | socrata | yes | [dataset](https://data.austintexas.gov/d/3syk-w9eu) |
| College Station | TX | `college_station_tx` | socrata | no | [dataset](https://data.cstx.gov/d/hrbn-znt6) |
| Collin County (appraisal district) | TX | `collin_county_tx` | socrata | some | [dataset](https://data.texas.gov/d/82ee-gbj5) |
| Hutto | TX | `hutto_tx` | arcgis | no | [dataset](https://services.arcgis.com/YZhxlqU7ABWQBGTG/arcgis/rest/services/City_of_Hutto_Building_Permits_2025_2026/FeatureServer/0) |
| San Antonio | TX | `san_antonio_tx` | ckan | yes | [dataset](https://data.sanantonio.gov/dataset/building-permits) |
| Tyler | TX | `tyler_tx` | arcgis | yes | [dataset](https://services5.arcgis.com/RmXXW3PwBZGOxlSe/arcgis/rest/services/Permit_Data_With_XY/FeatureServer/0) |
| Chesapeake | VA | `chesapeake_va` | arcgis | yes | [dataset](https://services1.arcgis.com/OAphVRUvJVpBRovs/arcgis/rest/services/BuildingActivity_public_882dacbef60b4def9c3ab6b66d349b29/FeatureServer/0) |
| Norfolk | VA | `norfolk_va` | socrata | no | [dataset](https://data.norfolk.gov/d/fahm-yuh4) |
| Virginia Beach | VA | `virginia_beach_va` | ckan | no | [dataset](https://data.virginia.gov/dataset/building-permits-applications1) |
| Bellevue | WA | `bellevue_wa` | arcgis | yes | [dataset](https://services1.arcgis.com/EYzEZbDhXZjURPbP/arcgis/rest/services/Bellevue_Permits_\(Pending_-_Ready_to_Issue_-_Issued_-_Open\)/FeatureServer/0) |
| Everett | WA | `everett_wa` | socrata | yes | [dataset](https://data.everettwa.gov/d/3w3u-656c) |
| Pierce County (unincorporated) | WA | `pierce_county_wa` | socrata | no | [dataset](https://open.piercecountywa.gov/d/nhnt-v7ka) |
| Seattle | WA | `seattle` | socrata | some | [dataset](https://data.seattle.gov/d/76t5-zqzr) |

**Refresh notes:** most feeds update daily. Los Angeles updates weekly. **New Jersey** (statewide, every municipality) is published with a 2–3 month lag, so use `issuedWithinDays` of 120 or more for it. Washington DC's and San Jose's feeds cover the last 30 days only. Boise is high-impact permits only.

### Privacy by design: no personal names

- **Owner, applicant and individual contractor name columns are never requested** from the city APIs.
- Where a city mixes people and companies in one column (Chicago contacts, Boston applicant, Cincinnati company), a name is kept **only if it carries a legal-entity designator**: LLC, Inc., Corp., Co., Company, Ltd., LP, LLP, PC, PLLC, or Joint Venture/JV. Strings like "ACME ELECTRIC CO / JOHN DOE" are split, and only the company part is kept.
- Emails and phone numbers inside free-text descriptions are masked.
- The address is the **project site** address the city publishes for the permit. Owner mailing addresses are never output.

### Input

| Field | What it does | Default |
|---|---|---|
| `cities` | Any IDs from the coverage table above | all |
| `states` | 2-letter state codes, e.g. `["TX","FL"]`; narrows the cities | none |
| `regions` | `northeast`, `midwest`, `south`, `west` (US Census regions) | none |
| `issuedWithinDays` | Permits issued in the last N days | 7 |
| `issuedFrom` / `issuedTo` | Exact issue-date window (YYYY-MM-DD) | none |
| `workCategories` | Normalized categories: New construction, Addition / alteration, Demolition, Roofing, Solar, Electrical, Plumbing, Mechanical / HVAC, Fire protection, Sign, Scaffold / shed / fence, Structural / foundation / earthwork, Other | all |
| `permitTypes` | Words in the city's own permit type or work class, e.g. `Sidewalk Shed`, `Commercial` | none |
| `minValuation` | Minimum declared job value in USD | none |
| `keywords` | Words in the description, e.g. `restaurant`, `ADU`, `pool`, `battery` | none |
| `onlyWithContractor` | Only permits that name a contractor business | false |
| `maxResults` | Total cap across cities, newest first | 100 |
| `maxResultsPerCity` | Optional cap per city | none |

Example: new construction worth $1M or more in the last 90 days, all cities:

```json
{ "issuedWithinDays": 90, "workCategories": ["New construction"], "minValuation": 1000000, "maxResults": 5000 }
```

### Output

```json
{
  "city": "Austin",
  "state": "TX",
  "permitNumber": "2025-036109 EP",
  "permitType": "Electrical Permit - Residential",
  "workClass": "New",
  "workCategory": "Electrical",
  "description": "New 2-story SFR with pool - 5 beds 6 baths ...",
  "status": "Active",
  "appliedDate": "2023-09-06",
  "issuedDate": "2026-10-17",
  "valuation": null,
  "address": "1902 HOLLY HILL DR",
  "zipCode": "78746",
  "latitude": 30.26199033,
  "longitude": -97.80259078,
  "housingUnitsChange": 1,
  "squareFeet": 5758,
  "contractorBusinessName": "Jd Trusted Electric LLC",
  "contractorRole": "Electrical Contractor",
  "contractors": [{ "name": "Jd Trusted Electric LLC", "role": "Electrical Contractor" }],
  "permitUrl": "https://abc.austintexas.gov/web/permit/public-search-other?...",
  "sourceUrl": "https://data.austintexas.gov/d/3syk-w9eu"
}
```

Results from all cities are merged **newest first**, with same-day permits balanced across cities. The dataset has two views: **Permits** and **Contractor leads**. A `RUN_SUMMARY` record gives per-city counts and any city that was temporarily unavailable. One city being down never fails the whole run.

### Run it daily

Schedule the Actor daily with `issuedWithinDays: 2` and send new permits to Google Sheets, a webhook, Make, Zapier or your CRM.

### Pricing

Pay per result: you are charged only for the permits returned. `maxResults` and your run's spending limit both cap the cost. See the **Pricing** tab.

### FAQ

**Is this legal to use?** Yes. All sources are official city, county or state open-data portals (Socrata, ArcGIS Hub/REST, CKAN, Carto) published for public reuse. Several are public domain (Seattle, Austin, Cincinnati, Baton Rouge, Montgomery County MD, New Orleans under CC0) or ODC-PDDL (San Francisco, Boston). San Antonio (City of San Antonio, data.sanantonio.gov) and Pittsburgh (City of Pittsburgh via WPRDC) data are used under CC BY 4.0, and San Jose data under CC0. Philadelphia data is used under the City of Philadelphia open-data terms via OpenDataPhilly. Required notice, per Chicago's Data Terms of Use: *"This site provides applications using data that has been modified for use from its original source, www.cityofchicago.org, the official website of the City of Chicago. The City of Chicago makes no claims as to the content, accuracy, timeliness, or completeness of any of the data provided at this site. The data provided at this site is subject to change at any time. It is understood that the data provided at this site is being used at one's own risk."*

**Why is Los Angeles empty for the last few days?** LA refreshes its permit dataset weekly. Use `issuedWithinDays` of 14 or more for LA.

**Why do some permits have no valuation or contractor?** Cities publish different fields. For example, San Francisco and LA don't publish contractor names, and NYC trade permits often omit a valuation. Missing values are `null`, never guessed.

**How is `workCategory` assigned?** From each city's permit type and work class, using fixed keyword rules, with the description as a fallback. Use `permitTypes` to filter on the city's original wording.

**Can you add my city?** The Actor is built to add any Socrata, CKAN or ArcGIS open-data city. Open an issue with the dataset link.

*Not affiliated with or endorsed by any of the cities listed.*

# Actor input Schema

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

Cities/counties to include. Leave empty for all sources (optionally narrowed by States or Regions).

## `states` (type: `array`):

Only include sources in these states, e.g. \["TX","CA"]. Combined with Regions. Applies to the Cities list (or to all sources if Cities is empty).

## `regions` (type: `array`):

US Census regions to include.

## `issuedWithinDays` (type: `integer`):

Permits issued in the last N days. Ignored when 'Issued from' is set. Note: Los Angeles refreshes weekly, so use 14+ days for LA.

## `issuedFrom` (type: `string`):

Optional start of the issue-date window.

## `issuedTo` (type: `string`):

Optional end of the issue-date window (defaults to today).

## `workCategories` (type: `array`):

Normalized work categories (derived from each city's permit type and work class).

## `permitTypes` (type: `array`):

Keep permits whose original permit type or work class contains any of these words, e.g. 'new', 'demolition', 'Sidewalk Shed', 'Commercial'.

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

Only permits with a declared job valuation at or above this amount. Permits without a valuation are excluded when set.

## `keywords` (type: `array`):

Keep permits whose description, type or work class contains any of these words, e.g. 'restaurant', 'ADU', 'pool', 'battery'.

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

Only return permits that list a contractor business (legal entity) name.

## `maxResults` (type: `integer`):

Maximum permits to return across all cities, newest first. You pay per result.

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

Optional cap per city (0 = no cap).

## `descriptionMaxLength` (type: `integer`):

Truncate descriptions to this many characters (0 = full text).

## Actor input object example

```json
{
  "cities": [
    "chicago",
    "nyc",
    "seattle",
    "austin"
  ],
  "issuedWithinDays": 7,
  "onlyWithContractor": false,
  "maxResults": 100,
  "descriptionMaxLength": 500
}
```

# Actor output Schema

## `permits` (type: `string`):

No description

## `runSummary` (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 = {
    "cities": [
        "chicago",
        "nyc",
        "seattle",
        "austin"
    ],
    "issuedWithinDays": 7,
    "maxResults": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("loomwise/city-building-permits").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": [
        "chicago",
        "nyc",
        "seattle",
        "austin",
    ],
    "issuedWithinDays": 7,
    "maxResults": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("loomwise/city-building-permits").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).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": [
    "chicago",
    "nyc",
    "seattle",
    "austin"
  ],
  "issuedWithinDays": 7,
  "maxResults": 100
}' |
apify call loomwise/city-building-permits --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,loomwise/city-building-permits"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

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