# US Building Permits (City Open Data) (`jetlaunch/us-building-permits-open-data`) Actor

Building permits from official city open-data portals (Chicago, New York City, San Francisco, Seattle, Austin, Los Angeles) in one schema, with optional new-since-last-run monitoring.

- **URL**: https://apify.com/jetlaunch/us-building-permits-open-data.md
- **Developed by:** [Chris O'Byrne](https://apify.com/jetlaunch) (community)
- **Categories:** Real estate, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

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 (City Open Data) reads building permits from the official open-data portals of four US cities and returns them in one normalized schema. Choose one or more cities, a date range and optional filters (permit type, minimum cost, keyword), and get clean rows you can export as JSON, CSV or Excel, call through the API or schedule. A monitor mode returns only permits you have not seen before.

Cities covered: New York City, San Francisco, Seattle and Austin. This Actor is not affiliated with or endorsed by any of these cities or by Socrata or Tyler Technologies. City names are used only to describe the data source.

### Who is it for?

- Contractors, suppliers and installers (roofing, solar, electrical, HVAC, signage) who want a daily list of new projects with a declared cost.
- Real estate investors, developers and analysts who track construction activity by city, permit type or project size.
- Researchers and journalists who need permit data from several cities in one consistent shape.

### What you get

One record per permit with these fields: `city`, `permit_number`, `permit_type`, `status`, `application_date`, `issue_date`, `address`, `work_description`, `declared_cost`, `fees`, `contractor_business_name`, `contractor_license_number` and `source_dataset_url`.

### How to use it

1. Open the Actor and pick one or more cities.
2. Set the date range: either "Issued in the last N days" or an exact "Issued from" and "Issued to" date.
3. Optionally add permit type words, a minimum declared cost and a keyword for the work description.
4. Set "Max results per city" and click Start. The default input returns the 25 most recent Seattle permits from the last 30 days.

### Input

| Field | What it does |
|---|---|
| Cities | One or more of New York City, San Francisco, Seattle, Austin. |
| Issued in the last N days | Date window counted back from today (UTC). Default 30. |
| Issued from / Issued to | Exact dates (YYYY-MM-DD). Override the days setting. |
| Permit types (contains) | Keep permits whose type text contains any of these words, ignoring case. |
| Minimum declared cost | Keep permits with a declared cost at or above this amount in USD. |
| Keyword in work description | Keep permits whose description contains this text, ignoring case. |
| Max results per city | Upper limit per city. Also caps your spend. |
| Mode | Search, or New since last run. |
| Monitor name | Names the saved memory used by New since last run. |
| Socrata app token | Optional. Not needed. |

Example input:

```json
{
  "cities": ["seattle", "austin"],
  "daysBack": 30,
  "keyword": "solar",
  "minCost": 10000,
  "maxResults": 100,
  "mode": "search"
}
```

### Output example

```json
{
  "city": "Seattle",
  "permit_number": "7168406-RR",
  "permit_type": "Roof",
  "status": "Issued",
  "application_date": null,
  "issue_date": "2026-10-20",
  "address": "7301 34TH AVE NW Seattle WA 98117",
  "work_description": "Remove 3 layers of comp shingles replace all plywood and install new comp shingles.",
  "declared_cost": 14465.5,
  "fees": null,
  "contractor_business_name": "Axis Roof and Gutter Inc",
  "contractor_license_number": null,
  "source_dataset_url": "https://data.seattle.gov/d/76t5-zqzr"
}
```

### New since last run (monitor mode)

Set Mode to "New since last run" and give the run a Monitor name. The Actor remembers which permits it has returned for that name and returns only new ones on later runs. Schedule it daily to build a feed of fresh permits.

- Permits come back oldest first, so nothing is skipped when the max results limit is reached. The next run continues where the last one stopped.
- The first run for a monitor name uses your date window as its starting point.
- Each run re-reads the previous 7 days so permits that a city posts late are still caught, without returning any permit twice.
- If you change the permit types, minimum cost or keyword, the monitor starts a new baseline for that name.
- The memory is kept in a key-value store named us-building-permits-monitor-state in your Apify account. Delete the record named STATE-<monitor name> there to reset a monitor.

### Pricing

You pay per permit returned. Platform usage is not billed on top of these events.

| Event | Price | When it is charged |
|---|---|---|
| Permit record | $0.003 | Each permit returned in Search mode. |
| New permit record | $0.005 | Each new permit returned in New since last run mode. |

Nothing is charged for permits that are not returned, so a search with no matches has no record charges. Examples: 25 permits in Search mode cost $0.075, and 1,000 cost $3.00. Set a maximum cost per run in the run options and the Actor stops at that limit.

### Data sources and licences

All data is read live from official city open-data portals through their public SODA APIs. No logins, scraping or proxies are used, and the Actor paces itself to about one request per second per portal.

| City | Dataset | Licence or terms shown by the portal |
|---|---|---|
| New York City | DOB NOW: Build, Approved Permits (rbx6-tga4) | NYC Open Data and NYC.gov Terms of Use. NYC's Open Data Law (Local Law 11 of 2012) requires public data to be made freely available on a single web portal. |
| San Francisco | Building Permits (i98e-djp9) | Open Data Commons Public Domain Dedication and License |
| Seattle | Building Permits (76t5-zqzr) | Public Domain |
| Austin | Issued Construction Permits (3syk-w9eu) | Public Domain U.S. Government, plus City of Austin Open Data Terms of Use |

Each record carries a `source_dataset_url` so you can check the original. You are responsible for following each portal's terms when you use the data. City data is provided as is and can be wrong or incomplete.

### Privacy

The Actor does not output owner names, applicant names, individual names or phone numbers. Contractor fields hold business names only. A contractor value is dropped when it does not clearly look like a business, which means a few real businesses with plain personal-style names can be missing. Phone numbers and email addresses found inside work descriptions are replaced with "\[removed]". Property addresses are included because they are part of the public permit record.

### FAQ

**Which dates do the filters use?** The permit issue date. Permits that have not been issued yet are not returned.

**Why are some fields empty?** Cities publish different fields. Contractor names come from New York City, Seattle and Austin, and the license number only from New York City. New York City does not publish an application date. None of the four cities publishes permit fees in these datasets, so `fees` is empty. Declared cost is empty when the city reports none or zero.

**How fresh is the data?** The cities state daily refreshes for these datasets. The newest permits can lag behind the city's own permit search.

**Do I need an app token?** No. A free Socrata app token is optional and raises the portal's request limits for large pulls.

**Can I use the API or schedules?** Yes. Use the Apify API, schedules, webhooks and integrations as with any Actor.

**Why does San Francisco show the same permit number twice?** San Francisco publishes one row per address for some permits, so one permit number can appear on several rows.

**Will more cities be added?** Possibly. Cities are added only after their open-data terms are checked.

### Limitations

- New York City data covers permits filed in DOB NOW: Build. Electrical, elevator and limited alteration permits are separate datasets and are not included, and older permits filed in the legacy system are not included.
- Permit type and status wording differs by city. Permit type filters match the city's own wording.
- Declared cost is the figure the applicant or city reports and is not collected for every permit type.
- Contractor data is missing for San Francisco because that dataset does not publish it.
- Results are capped at 50,000 permits per city per run.

### Support

Found a bug or a changed portal field? Open an issue in the Issues tab of this Actor. Include your run link and input.

# Actor input Schema

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

Cities to query. Each city is read from its own official open-data portal.

## `daysBack` (type: `integer`):

Used when 'Issued from' is empty. Counts back from today (UTC) or from 'Issued to' when that is set.

## `dateFrom` (type: `string`):

First permit issue date to include. Overrides 'Issued in the last N days' when set.

## `dateTo` (type: `string`):

Last permit issue date to include. Leave empty for today.

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

Optional. Keep a permit when its permit type text contains any of these words, ignoring case. Examples: new construction, renovation, electrical, demolition, roof. Type names differ by city.

## `minCost` (type: `integer`):

Optional. Only permits whose declared cost is at least this amount. Permits with no declared cost are left out when this is set.

## `keyword` (type: `string`):

Optional. Only permits whose work description contains this text, ignoring case. Example: solar, roof, kitchen, warehouse.

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

Upper bound on permits returned for each selected city. You are charged per permit returned, so this also caps your spend.

## `mode` (type: `string`):

'Search' returns every permit that matches. 'New since last run' returns only permits not returned by an earlier run with the same monitor name, oldest first, and remembers them for the next run.

## `monitorName` (type: `string`):

Only used in 'New since last run' mode. Runs that share a name share their memory of permits already returned. Use a different name for each saved search.

## `appToken` (type: `string`):

Optional. A free Socrata app token raises the portals' request limits. The Actor works without one.

## Actor input object example

```json
{
  "cities": [
    "seattle"
  ],
  "daysBack": 30,
  "permitTypes": [],
  "maxResults": 25,
  "mode": "search",
  "monitorName": "default"
}
```

# Actor output Schema

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

Permit records in the default dataset.

# 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": [
        "seattle"
    ],
    "daysBack": 30,
    "maxResults": 25
};

// Run the Actor and wait for it to finish
const run = await client.actor("jetlaunch/us-building-permits-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": ["seattle"],
    "daysBack": 30,
    "maxResults": 25,
}

# Run the Actor and wait for it to finish
run = client.actor("jetlaunch/us-building-permits-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": [
    "seattle"
  ],
  "daysBack": 30,
  "maxResults": 25
}' |
apify call jetlaunch/us-building-permits-open-data --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jetlaunch/us-building-permits-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/JWecAFc3H6sIOeIRD/builds/Y5gQJ9FqTYfMxWgxQ/openapi.json
