# GovData Labs — US Building Permits Feed (`govdatalabs/govdata-labs-building-permits-feed`) Actor

GovData Labs normalizes building permits from official US city, county, and state open-data APIs.

- **URL**: https://apify.com/govdatalabs/govdata-labs-building-permits-feed.md
- **Developed by:** [GovData Labs](https://apify.com/govdatalabs) (community)
- **Categories:** Lead generation, Real estate, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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

## GovData Labs — US Building Permits Feed

A normalized building-permit feed from official US open-data APIs. Version 1 ships 26 verified sources (cities, two counties, and New Jersey's statewide construction file). Each source is a config object: endpoint, date field, and a mapper into one schema. Adding a city is a new config, not a new Actor.

For contractors, suppliers, and lead products that want solar, roofing, HVAC, electrical, and other trade signals without learning 26 column layouts.

### What you get

- `city`, `state`, `permit_number`
- `issued_on`, `applied_on`, `status`, `permit_type`
- `work_description`
- `trade_tags` from a keyword classifier: solar, roofing, hvac, electrical, plumbing, new construction, demolition, pool, windows, siding, fence, addition, ev charger, fire protection
- `valuation`
- `address`, `latitude`, `longitude` when the source publishes them
- `contractor_name` and `contractor_license` when the source publishes them
- `owner_name` and `applicant_name` when those fields are public
- `source_id`, `source_url`, `fetched_at`

Rows with no published valuation are kept unless you set `minValuation`. A keyword filter matches the type, the description, and the tags, so `solar` catches both the word and the tag.

### Who it is for

- Trade contractors who want last week's permits in a few cities
- A nightly "new since last run" job that only pays for new or changed permits
- Anyone who needs Chicago, Seattle, Dallas, Los Angeles, and the other sources below in one schema

### How a run works

Pick city ids, a date range, optional permit-type substrings, trade keywords, and a minimum valuation. If you omit dates, the run uses the last 7 days through today. If you omit cities, it uses Chicago, Seattle, Dallas, Austin, and Cincinnati. `all` includes every source, including the large New Jersey file.

Each source is queried with the date pushed into SoQL, CKAN SQL, or Carto SQL. Pages stop at 1,000 rows. A source stops after 20 pages so a wide query cannot scan an entire historical file. `maxResults` (default 100) stops the run across cities.

"Only changes since last run" keeps one snapshot per city. The first run stores a baseline. Later runs re-read from the day before the watermark and emit only new or changed permits.

### Pricing

Pay per event. You pay only for what a run returns:

| Event | Price | When |
| --- | ---: | --- |
| `actor-start` | $0.010 | Once per valid run |
| `permit-result` | $0.005 | Each output row |
| `change-detected` | $0.005 | Each new or changed row after that city's baseline |

One hundred permits, the default cap, cost about $0.51. One thousand permits are about $5.01. A typical thousand-row pull is a few minutes at 512 MB, well under $0.02 of Apify platform compute, billed separately.

### Example input

```json
{
  "cities": ["chicago", "seattle", "austin"],
  "dateFrom": "2026-10-01",
  "dateTo": "2026-10-31",
  "tradeKeywords": ["solar", "roofing"],
  "minValuation": 5000,
  "maxResults": 100
}
```

### Example output

Chicago row retrieved live on 31 October 2026. Descriptions and costs change every day.

```json
{
  "city": "Chicago",
  "state": "IL",
  "permit_number": "B200517587",
  "issued_on": "2026-10-29",
  "permit_type": "PERMIT – EXPRESS PERMIT PROGRAM",
  "work_description": "LINE VOLTAGE ELECTRICAL WORK. NEW PERMANENT 200 AMP SERVICE...",
  "trade_tags": ["electrical"],
  "valuation": 10511,
  "address": "2500 W FARWELL AVE, Chicago, IL",
  "latitude": 42.00599,
  "longitude": -87.69265,
  "contractor_name": null,
  "source_id": "chicago",
  "source_url": "https://data.cityofchicago.org/d/ydr8-5enu",
  "fetched_at": "2026-10-31T00:00:00.000Z"
}
```

Chicago's building-permits dataset does not include a contractor name. Seattle, Austin, Dallas, Cincinnati, and several other sources do.

### Verified sources

Checked live on 31 October 2026. A source is listed only if a sample row came back with usable columns.

| Id | Place | API | Dataset |
| --- | --- | --- | --- |
| `chicago` | Chicago, IL | Socrata | [ydr8-5enu](https://data.cityofchicago.org/d/ydr8-5enu) |
| `seattle` | Seattle, WA | Socrata | [76t5-zqzr](https://data.seattle.gov/d/76t5-zqzr) (also on cos-data.seattle.gov) |
| `dallas` | Dallas, TX | Socrata | [e7gq-4sah](https://www.dallasopendata.com/Services/Building-Permits/e7gq-4sah) |
| `los-angeles` | Los Angeles, CA | Socrata | [pi9x-tg5x](https://data.lacity.org/d/pi9x-tg5x) |
| `cincinnati` | Cincinnati, OH | Socrata | [uhjb-xac9](https://data.cincinnati-oh.gov/d/uhjb-xac9) |
| `austin` | Austin, TX | Socrata | [3syk-w9eu](https://data.austintexas.gov/d/3syk-w9eu) |
| `san-francisco` | San Francisco, CA | Socrata | [i98e-djp9](https://data.sfgov.org/d/i98e-djp9) |
| `new-york` | New York, NY | Socrata | DOB permit issuance [ipu4-2q9a](https://data.cityofnewyork.us/d/ipu4-2q9a) |
| `new-york-dob-now` | New York, NY | Socrata | DOB NOW approved permits [rbx6-tga4](https://data.cityofnewyork.us/d/rbx6-tga4) |
| `new-orleans` | New Orleans, LA | Socrata | [72f9-bi28](https://data.nola.gov/d/72f9-bi28) |
| `mesa` | Mesa, AZ | Socrata | [dzpk-hxfb](https://citydata.mesaaz.gov/d/dzpk-hxfb) |
| `marin-county` | Marin County, CA | Socrata | [mkbn-caye](https://data.marincounty.gov/d/mkbn-caye) |
| `baton-rouge` | Baton Rouge, LA | Socrata | [7fq7-8j7r](https://data.brla.gov/d/7fq7-8j7r) |
| `boston` | Boston, MA | CKAN SQL | [Approved Building Permits](https://data.boston.gov/dataset/approved-building-permits) resource `6ddcd912-32a0-43df-9908-63574f8c7e77` |
| `philadelphia` | Philadelphia, PA | Carto SQL | `permits` on phl.carto.com |
| `montgomery-residential` | Montgomery County, MD | Socrata | [m88u-pqki](https://data.montgomerycountymd.gov/d/m88u-pqki) |
| `montgomery-commercial` | Montgomery County, MD | Socrata | [i26v-w6bd](https://data.montgomerycountymd.gov/d/i26v-w6bd) |
| `cambridge` | Cambridge, MA | Socrata | alterations [qu2z-8suj](https://data.cambridgema.gov/d/qu2z-8suj) |
| `cambridge-new` | Cambridge, MA | Socrata | new construction [9qm7-wbdc](https://data.cambridgema.gov/d/9qm7-wbdc) |
| `kansas-city` | Kansas City, MO | Socrata | [ntw8-aacc](https://data.kcmo.org/d/ntw8-aacc) |
| `corona` | Corona, CA | Socrata | [2agx-camz](https://corstat.coronaca.gov/d/2agx-camz) |
| `gainesville` | Gainesville, FL | Socrata | [p798-x3nx](https://data.cityofgainesville.org/d/p798-x3nx) |
| `honolulu` | Honolulu, HI | Socrata | [4vab-c87q](https://data.honolulu.gov/d/4vab-c87q) static through 2025-06-30 |
| `new-jersey` | New Jersey municipalities | Socrata | [w9se-dmra](https://data.nj.gov/d/w9se-dmra) |
| `collin-county` | Collin County, TX | Socrata | [82ee-gbj5](https://data.texas.gov/d/82ee-gbj5) |
| `somerville` | Somerville, MA | Socrata | [nneb-s3f7](https://data.somervillema.gov/d/nneb-s3f7) filtered to Permitting |

#### Dropped after a live check

- Los Angeles `yv23-pmwf` returned HTTP 403. `pi9x-tg5x` (2020 onward) is used instead.
- Boston Socrata id `msk6-43c6` is gone (HTTP 404). The CKAN resource above replaces it.
- Dallas on the host without `www` 404s. `www.dallasopendata.com` works.
- Seattle `mags-97de` 404s. `76t5-zqzr` is the live building-permits set.
- New York `xfyi-uyt5` returned HTTP 403. DOB issuance and DOB NOW are both included.
- Denver Building Permits FeatureServer responded but every layer query returned zero features on 31 October 2026, so it is not enabled. `queryArcGis()` is in the source for the day that layer has rows again.
- Nashville `3h5w-q8b7` and several other guessed portal ids (Hartford, Raleigh, Louisville, Sacramento, Fort Worth) returned portal HTML rather than SODA JSON. They are not included.
- A handful of hosts failed DNS (Las Vegas, Salt Lake City, Santa Monica, Glendale, Madison). They are not included.

Mesa filters on `opened_date` because that portal does not publish an issue date; the value is stored as `applied_on`. Philadelphia's `permits` table includes zoning permits as well as building permits. Honolulu will return nothing for "last 7 days" because the file stops at 30 June 2025.

Each row's `source_url` points at the portal dataset or, when the city publishes one, the permit deep link. Data is published as public open data by the named city, county, or state. Confirm that portal's terms before you redistribute an extract.

### Limits

- Default 100 results, hard cap 20,000.
- 20 pages of 1,000 rows scanned per source per run.
- 200 ms between SODA calls to the same host, with retry and backoff.
- Optional Socrata app token. It does not apply to Boston (CKAN) or Philadelphia (Carto).
- Per-city snapshots keep at most 2,000 hashes.

### Disclaimer

Data comes from official public sources and may lag the permitting office. It is not a permit, a permission to build, or a statement by the city. Confirm the job with the building department before you treat a row as a lead you can rely on.

# Changelog

This Actor's version history is a separate document: https://apify.com/govdatalabs/govdata-labs-building-permits-feed/changelog.md

# Actor input Schema

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

Source ids. Choose all for every configured source, including the large New Jersey feed. Omit this field and the run uses Chicago, Seattle, Dallas, Austin, and Cincinnati.

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

Inclusive YYYY-MM-DD. Defaults to 7 days before the to-date. In change-tracking mode the watermark can move this later.

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

Inclusive YYYY-MM-DD. Defaults to today.

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

Case-insensitive substrings. A row is kept when its permit type contains any of them.

## `tradeKeywords` (type: `array`):

Keep rows whose type, description, or trade tag contains a keyword. Tags include solar, roofing, hvac, electrical, plumbing, new construction, demolition, and pool.

## `minValuation` (type: `number`):

Drop permits below this amount. Rows with no published valuation are dropped when this is set.

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

Cap on output rows across all cities. Each row is billed as permit-result. Default 100.

## `onlyChangesSinceLastRun` (type: `boolean`):

Each city keeps its own snapshot. The first run stores a baseline and bills permit-result only. Later runs emit new or changed permits and also bill change-detected.

## `snapshotStoreName` (type: `string`):

Named key-value store. One record per city.

## `requestSpacingMs` (type: `integer`):

Minimum delay between SODA requests to the same host. Default 200.

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

Optional. Anonymous access works for light runs. You can also set SOCRATA_APP_TOKEN. Boston uses CKAN and Philadelphia uses Carto; the token does not apply to them.

## Actor input object example

```json
{
  "cities": [
    "chicago",
    "seattle",
    "dallas",
    "austin",
    "cincinnati"
  ],
  "tradeKeywords": [
    "solar",
    "roofing"
  ],
  "maxResults": 100,
  "onlyChangesSinceLastRun": false,
  "snapshotStoreName": "building-permits-snapshots",
  "requestSpacingMs": 200
}
```

# Actor output Schema

## `results` (type: `string`):

Permit rows written to the default dataset.

## `resultCount` (type: `string`):

No description

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

No description

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

No description

## `errorCount` (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 = {
    "tradeKeywords": [
        "solar",
        "roofing"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("govdatalabs/govdata-labs-building-permits-feed").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 = { "tradeKeywords": [
        "solar",
        "roofing",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("govdatalabs/govdata-labs-building-permits-feed").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 '{
  "tradeKeywords": [
    "solar",
    "roofing"
  ]
}' |
apify call govdatalabs/govdata-labs-building-permits-feed --silent --output-dataset

```

## MCP server setup

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

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/TZfohoYxljXVo4Ioc/builds/CRbb4sOuZQuHzbSKJ/openapi.json
