# US Building Permits API: 7 Official City & County Sources (`jp-data-lab/us-building-permits-official-open-data`) Actor

Newly issued building permits from seven official US city and county open data portals, in one schema: permit type, status, issue date, work-site address, valuation and work tags. Public-domain licensed sources only. No personal names, phones or emails.

- **URL**: https://apify.com/jp-data-lab/us-building-permits-official-open-data.md
- **Developed by:** [JP Data Lab](https://apify.com/jp-data-lab) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 building permits

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

## US Building Permits API: 7 Official City & County Sources

Get newly issued building permits from seven official US city and county open data portals in **one JSON schema**. Every source carries an explicit public-domain style licence, confirmed from the portal's own dataset metadata.

| `source` | Jurisdiction | Dataset | Licence |
|---|---|---|---|
| `san-francisco` | San Francisco, CA | [Building Permits](https://data.sf.gov/d/i98e-djp9) | Open Data Commons PDDL |
| `seattle` | Seattle, WA | [Building Permits](https://data.seattle.gov/d/76t5-zqzr) | Public Domain |
| `austin` | Austin, TX | [Issued Construction Permits](https://data.austintexas.gov/d/3syk-w9eu) | Public Domain U.S. Government |
| `cincinnati` | Cincinnati, OH | [Cincinnati Building Permits](https://data.cincinnati-oh.gov/d/uhjb-xac9) | Public Domain |
| `montgomery-county-md` | Montgomery County, MD | [Residential Permit](https://data.montgomerycountymd.gov/d/m88u-pqki) | Public Domain |
| `new-orleans` | New Orleans, LA | [Permits](https://data.nola.gov/d/rcm3-fn58) | CC0 1.0 |
| `cambridge-ma` | Cambridge, MA | [Building Permits: New Construction](https://data.cambridgema.gov/d/9qm7-wbdc) | Open Data Commons PDDL |

Use it for construction market research, new-project alerts by trade, solar and roofing market sizing, or AI agents that need to answer "what is being built in this city right now?".

### Output

One item per permit:

```json
{
  "id": "new-orleans:26-31990-SATT",
  "source": "new-orleans",
  "jurisdiction": "New Orleans, LA",
  "state": "LA",
  "permitNumber": "26-31990-SATT",
  "url": "https://data.nola.gov/d/rcm3-fn58",
  "attribution": "City of New Orleans, Safety and Permits, https://data.nola.gov/d/rcm3-fn58 (CC0 1.0)",
  "category": "sign",
  "permitType": "Attached Sign",
  "propertyUse": "Business Use",
  "siteType": "non_residential",
  "status": "Permit Issued",
  "appliedAt": "2026-10-29",
  "issuedAt": "2026-10-30",
  "address": "1413 Upperline St",
  "city": "New Orleans",
  "zip": null,
  "latitude": 29.92498,
  "longitude": -90.10758,
  "housingUnits": null,
  "valuation": null,
  "contractorCompany": null,
  "workTags": [],
  "matchedKeywords": [],
  "scrapedAt": "2026-10-31T09:00:00+00:00"
}
```

| Field | Meaning |
|---|---|
| `category` | One of `new_construction`, `alteration`, `demolition`, `roofing`, `electrical`, `mechanical`, `plumbing`, `sign`, `other`. Worked out from the permit type columns |
| `permitType` | The source's own permit type wording |
| `propertyUse` | The source's own use or occupancy wording. Cincinnati uses building code classes such as `I-1` |
| `siteType` | `non_residential` when the property use is confirmed as commercial, institutional or industrial. Otherwise `residential_or_unknown` |
| `address`, `latitude`, `longitude` | Work site, for `non_residential` permits only. `null` for homes and for anything not confirmed. See "Personal data" below |
| `city`, `zip` | City and ZIP code of the work site, for every permit where the source gives them |
| `valuation` | Published project value in USD. A published `0` is returned as `null` |
| `contractorCompany` | Business name only, and only where the source has a company column. See "Personal data" below |
| `workTags` | Topics found in the source's work description: `solar`, `battery`, `ev-charger`, `generator`, `roof`, `hvac`, `pool`, `adu`, `kitchen`, `bathroom`, `deck`, `foundation`, `windows`, `siding`, `fence`, `sprinkler`, `elevator`, `tenant-improvement` |
| `matchedKeywords` | Which of your keywords matched |
| `url` | The official permit page for `non_residential` permits where the source links one. Otherwise the dataset page |

### Input

| Field | Default | |
|---|---|---|
| `cities` | all | Any of the `source` values above |
| `publishedWithinDays` | 7 | Permits issued in the last N days. `0` = no date limit |
| `permitTypes` | none | Any of the `category` values |
| `minValuation` | none | Minimum published value in USD. Permits with no published value are dropped |
| `nonResidentialOnly` | `false` | Keep only `non_residential` permits, the ones with a street address. Skips Montgomery County and Cambridge |
| `keywords` | none | Work description or permit type contains any keyword |
| `maxItems` | 200 | Total for the run, shared evenly across cities. You pay per result |

A default run takes under a minute. Schedule it weekly, or daily with `publishedWithinDays: 3`, and remove repeats using `id`.

### Personal data

This Actor is built not to return personal data:

- **No names, phones or emails.** Owner, applicant, contractor-contact, architect and engineer columns are never requested from the source.
- **No free-text descriptions.** Real description fields contain private email addresses and staff names and phone numbers, so they are used only for keyword search and `workTags`, and are never returned.
- **Contractor companies are filtered.** Company columns sometimes hold a person's name, such as `Company/Person`, `Person DBA Company`, or just a person. Only the part containing a business word (`LLC`, `Inc`, `Plumbing` and similar) is returned. Others come back as `null`. A trade name that itself contains a name, such as `Jane Doe Plumbing`, is still returned as a business name.
- **No home addresses.** A street address or exact coordinates on a house permit would identify a household, so `address`, `latitude` and `longitude` are `null` and `url` points to the dataset page unless the property use is on a per-source list of confirmed non-residential uses. Apartments, mixed use, blank uses and unknown values are treated as homes. City and ZIP code are still returned.

The permit number is kept so you can check a permit with the issuing government. This Actor is not suited to door-to-door or mail lists of homeowners.

### Limitations

- **Sources lag** by one to three days, so a small day range can be empty for some cities. Quiet sources are normal: Cambridge issues a few new-construction permits a week.
- **Coverage differs by source.** Montgomery County covers residential permits only and Cambridge covers new construction only. New Orleans has no ZIP column.
- **Most permits have no street address.** Most permits are for homes, and Montgomery County and Cambridge never return one. Set `nonResidentialOnly` for address-ready results.
- **Some fields are often empty.** Recent Cincinnati permits have no coordinates, about a third of recent Austin permits have none, and most Austin permits have no valuation, so `minValuation` removes most of Austin. San Francisco, Seattle, Montgomery County, New Orleans and Cambridge rarely or never give a `contractorCompany`.
- **Valuation is not comparable across cities.** It is what the applicant or city published, and trade permits often have none.
- **`category` reflects the permit type, not the work.** San Francisco files most jobs as alterations, so to find San Francisco roof work use the `roof` keyword or `workTags`, not the `roofing` type.
- **`permitTypes` is applied after reading,** at most 20,000 rows per city. Use a shorter date range if the log says the limit was reached.
- **Chicago, New York City and Los Angeles are not included,** because their licence terms could not be confirmed.
- If one source is down, the run still succeeds with the others. See `RUN_SUMMARY` for per-source counts and errors.
- Not affiliated with any of these governments. Always check the official record before relying on a permit.

### Data sources and attribution

Each item carries its own `attribution` field with the publisher, dataset link and licence, so you can keep the credit when you pass the data on.

***

### 日本語

米国の 7 つの市・郡の公式オープンデータから、発行された建築許可を同じ形式で取得します。許諾はポータルのメタデータで確認し、パブリックドメイン相当のものだけを使っています。氏名・電話・メールと自由記述は出力しません。番地と座標は、商業・公共の建物と確認できた許可だけに出します。住宅と、用途が確認できない許可は、市と郵便番号までです。

# Actor input Schema

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

Which official open data sources to read. Leave all selected for every source.

## `publishedWithinDays` (type: `integer`):

Only permits issued in the last N days. 0 = no date limit (newest first, up to the result limit). Sources usually lag by one to three days.

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

Optional. Leave empty for all types.

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

Optional. Keep permits whose published project value is at least this amount. Permits with no published value are dropped when you set this.

## `nonResidentialOnly` (type: `boolean`):

Keep only permits confirmed as commercial, institutional or industrial. These are the permits that include a street address and coordinates. Montgomery County and Cambridge have none.

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

Keep permits whose work description or permit type contains any of these words, e.g. solar, roof, pool. Case-insensitive. The description text is searched but not returned; see matchedKeywords in the output.

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

Total for the whole run, shared evenly across cities, newest first within each city. You are charged per result.

## Actor input object example

```json
{
  "cities": [
    "san-francisco",
    "seattle",
    "austin",
    "cincinnati",
    "montgomery-county-md",
    "new-orleans",
    "cambridge-ma"
  ],
  "publishedWithinDays": 7,
  "permitTypes": [],
  "nonResidentialOnly": false,
  "keywords": [],
  "maxItems": 200
}
```

# Actor output Schema

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

One item per building permit: jurisdiction, permit number, category, type, status, issue date, work-site address, coordinates, valuation, contractor company where available, work tags, source URL and attribution.

## `runSummary` (type: `string`):

Rows read and results returned per source in this run, with any source errors.

# 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": [
        "san-francisco",
        "seattle",
        "austin",
        "cincinnati",
        "montgomery-county-md",
        "new-orleans",
        "cambridge-ma"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("jp-data-lab/us-building-permits-official-open-data").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": [
        "san-francisco",
        "seattle",
        "austin",
        "cincinnati",
        "montgomery-county-md",
        "new-orleans",
        "cambridge-ma",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("jp-data-lab/us-building-permits-official-open-data").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": [
    "san-francisco",
    "seattle",
    "austin",
    "cincinnati",
    "montgomery-county-md",
    "new-orleans",
    "cambridge-ma"
  ]
}' |
apify call jp-data-lab/us-building-permits-official-open-data --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jp-data-lab/us-building-permits-official-open-data"
        }
    }
}
```

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/TZgDID2Cjg2NQdtcS/builds/4DTKTwDl9ie51pXXK/openapi.json
