# US Building Permits Scraper — Construction & Contractor Leads (`curative_blanket/us-building-permits`) Actor

Fresh building permits from 5 US cities (Austin, Chicago, NYC, LA, Seattle) via official open data. Normalized schema, incremental, pay-per-result. Built for solar/roofing/HVAC leads, proptech, and AI agents.

- **URL**: https://apify.com/curative\_blanket/us-building-permits.md
- **Developed by:** [Salim](https://apify.com/curative_blanket) (community)
- **Categories:** Lead generation, Real estate, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 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?

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 — Multi-City, Daily & Incremental

Fresh **building permits from major US cities**, straight from official government open-data portals. One Actor, pick your city — Austin, Chicago, New York, Los Angeles, Seattle, San Francisco (more added regularly). Normalized into one clean schema: permit type, work class, address, valuation, contractor, status, and issue date.

**Pay only for results.** No subscription. A run that returns nothing costs nothing.

### Why this feed

- **Local where it matters.** A solar installer in Chicago doesn't want a national blob — they want *Chicago* permits. Pick the city; get exactly that.
- **Incremental by default.** Each scheduled run emits only permits (by permit number) issued since the last run. Schedule it daily and get just that day's new permits.
- **One schema across cities.** Every city's columns are normalized to the same fields, so your workflow doesn't change when you switch cities.
- **Official source, no scraping.** Pulled from each city's government Socrata open-data portal. Authoritative, no anti-bot breakage.
- **Agent-ready.** Clean JSON, stable fields, pay-per-result — drop it into an MCP workflow or an AI lead agent.

### Output fields

`city`, `permitNumber`, `permitType`, `workClass`, `status`, `description`, `address`, `addressCity`, `addressState`, `addressZip`, `valuation`, `contractor`, `applicant`, `latitude`, `longitude`, `issuedDate`, `scrapedAt` — plus all original city fields passed through.

### Who uses this

Solar / roofing / HVAC and contractor lead generation · proptech and construction analytics · market research · AI agents answering "what permits were issued near me this week."

### Cities

Austin, Chicago, New York, Los Angeles, Seattle, **San Francisco** — with a city-override option for any other US city on the Socrata open-data platform. Need a specific city added? Open an issue.

### Billing model

This Actor bills via Apify's **automatic per-dataset-item ("Result") event** — exactly one item written to the default dataset equals exactly one billable result. The code never calls `Actor.charge()`, so there is no double-billing, and a run that emits **zero** new permits writes nothing to the default dataset and therefore **costs $0** (the no-results notice goes to the run log, `OUTPUT`, and a non-default `run-reports` dataset). Set the **Result** event price (`apify-default-dataset-item`) the same as the Austin actor ($0.0025/result), with no custom charge event.

### Schedule it

Set a daily schedule with your city and `newSinceDays: 2`, `incremental: true` for a clean daily feed of new permits.

# Actor input Schema

## `city` (type: `string`):

Which city's permits to pull.

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

Return permits issued in the last N days. Default 30 ensures a cold first run always returns data. For a daily scheduled feed, 2–3 is typical.

## `tradeTypes` (type: `array`):

Only emit permits whose type, class, or description contains one of these keywords (case-insensitive). Leave empty for all trades. Examples: solar, roofing, HVAC, electrical, plumbing, new construction.

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

Cost guard — cap on the number of permits emitted (and billed) per run.

## `incremental` (type: `boolean`):

On: each run emits only permits (by permit number) not seen in prior runs.

## `resetDedup` (type: `boolean`):

Clears the 'seen' memory so the next run re-emits everything. Use for the first run or a health check.

## `domainOverride` (type: `string`):

Point at a city not yet in the registry, e.g. 'data.sandiego.gov'. Requires datasetIdOverride.

## `datasetIdOverride` (type: `string`):

Socrata 4x4 dataset ID for the override city.

## `dateFieldOverride` (type: `string`):

Issue-date column name for the override city.

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

Optional free token for higher rate limits. Falls back to SOCRATA\_APP\_TOKEN env var.

## Actor input object example

```json
{
  "city": "austin",
  "daysBack": 30,
  "tradeTypes": [],
  "maxResults": 1000,
  "incremental": true,
  "resetDedup": false
}
```

# Actor output Schema

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

Issued building permits normalized to a common schema. One item per permit. Empty on runs where incremental mode found no new permits (no charge).

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

JSON summary of the run: city, date window, scanned count, emitted (billable) count, incremental flag, and dataset ID.

# 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("curative_blanket/us-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 = {}

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

```

## MCP server setup

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