# johto Trade Permits: Building Permit Leads (Solar, Roofing) (`johto.data/us-city-building-permits-leads`) Actor

johto Trade Permits: new US building permits from official city open-data portals (LA, NYC, Chicago, SF, Austin, Seattle + 4 more) in one schema: permit type, work description, address, valuation, contractor, owner, lat/lon. Filter by trade keyword (solar, roof, pool, ADU) and value. $0.003/permit.

- **URL**: https://apify.com/johto.data/us-city-building-permits-leads.md
- **Developed by:** [Jo](https://apify.com/johto.data) (community)
- **Categories:** Lead generation, Real estate, Agents
- **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

## johto Trade Permits: Building Permits Scraper – Solar, Roofing & Construction Leads from 10 US Cities

**johto Trade Permits: a building permits scraper for 10 US cities and counties, at $3 per 1,000 permits.** It pulls official open data from LA, NYC, Chicago, Austin, Seattle, SF and 4 more, with contractor name, phone (Austin and Seattle), valuation and address. Use it to find solar permits, roofing, HVAC and new-construction leads.

**Quick start:** click **Start**. The prefilled input (LA, NYC and Chicago, keyword solar, 10 per city) returns up to 30 permits in about a minute for at most $0.095 ($0.003 each plus the $0.005 start fee). Raise `maxItems` (per city) for the full list. New Apify accounts include free monthly credits.

Get **newly issued building permits** from 10 US cities and counties (Los Angeles, New York City, Chicago, San Francisco, Austin, Seattle, Cincinnati, Mesa AZ, Baton Rouge, Marin County) in **one clean, normalized dataset**. Each record includes permit type, work description, address, ZIP, job valuation, contractor, owner and coordinates. Use it to find **construction leads** for roofing, solar, pool, ADU, HVAC, remodeling, demolition, building-supply and insurance businesses.

The data comes from each city's **official open-data portal (Socrata API)**. It is public data published for reuse. No logins, no CAPTCHAs, no proxies.

### For AI agents

**Questions this answers:**

- Find solar permits issued in Los Angeles this week
- New construction permits over $1M in Chicago
- Roofing contractor leads from Austin permits

**Call it when:**

- The user wants permits issued recently (daysBack 1-365) in one of: los-angeles, new-york, chicago, austin, seattle, san-francisco, cincinnati, mesa, baton-rouge, marin-county.
- The user wants trade-filtered permits (keywords such as solar, roof, pool, ADU, demolition) or a minimum valuation.
- A scheduled workflow needs only permits it has not seen before (onlyNew: true).

**Don't call it when:**

- The city is not in the 10 listed portals (the Actor returns nothing useful there).
- The user needs homeowner phone/email: permits carry address, contractor and sometimes owner name only, no contact details.
- The user needs a full historical permit history for one property across many years in other cities.

Use this instead of `pink_comic/building-permits-construction-leads` when you need one of these 10 city portals in a single normalized schema with contractor/owner/APN/geo fields and `onlyNew` dedupe for schedules. If price per row is all that matters, pink_comic is cheaper ($0.002 vs our $0.003 per row on 2026-10-22).

**Input - Solar and roofing permits in LA and Austin, last 14 days:**

```json
{"cities": ["los-angeles", "austin"], "daysBack": 14, "keywords": ["solar", "roof"], "minValuation": 10000, "maxItems": 25}
```

**Input - Scheduled only-new feed:**

```json
{"cities": ["chicago"], "daysBack": 7, "keywords": ["pool"], "onlyNew": true, "maxItems": 50}
```

**Output:** one dataset row per permit. Real row from run `R4coRu5EEwc6f8qGP` (long lists trimmed, named people redacted):

```json
{
 "city": "los-angeles",
 "permitNumber": "26010-20001-00023",
 "issueDate": "2026-10-15T00:00:00.000",
 "permitType": "Bldg-Alter/Repair / 1 or 2 Family Dwelling",
 "workDescription": "SUPPLEMENTAL PERMIT TO 26010-20000-00023 TO:1- RELOCATE THE ADU ENTRY DOOR FROM THE SOUTH ELEVATION TO THE WEST ELEVATION AND RECONFIGURE WINDOW ON WEST ELEVATION.2- RECONFIGURE ADU KITCHEN 3- RECONFIGURE THE FIRST-FLOOR BATHROOM LAYOUT OF THE TWO-STORY SB 9 DWELLING AND REPLACE WINDOW TYPE \"D\" WITH WINDOW TYPE \"E\".4- REMOVE WALL UNDER AWNING",
 "address": "10715-10715 1/2 W CANTLAY ST",
 "zip": "91352",
 "valuation": 10000,
 "status": "Issued",
 "contractorName": null,
 "contractorLicense": null,
 "ownerName": null,
 "lat": 34.20326108,
 "lon": -118.36429322,
 "apn": "2410013023",
 "sourceUrl": "https://data.lacity.org/d/pi9x-tg5x"
}
```

**Price:** $0.003 per permit (event `permit`) + $0.005 per run start (`apify-actor-start`). `maxItems` applies **per city**, so 2 cities x 25 = up to 50 charged rows ($0.155 incl. start).

**Limits:**

- 10 cities only (enum `cities`).
- `maxItems` is per city; default 100.
- Portals lag issuance by days to weeks; some cities leave contractor/owner null (see sample).
- No homeowner contact data.

**Call it:** MCP `https://mcp.apify.com/?tools=johto.data/us-city-building-permits-leads` (tool `johto-dot-data--us-city-building-permits-leads`), or `POST https://api.apify.com/v2/acts/johto.data~us-city-building-permits-leads/run-sync-get-dataset-items` with `Authorization: Bearer <APIFY_TOKEN>` and the JSON input.
**Agent pays with USDC (x402), no Apify account:** `https://mcp.apify.com/?tools=johto.data/us-city-building-permits-leads&payment=x402`

**Quick, cheap first call:** An empty-input call returns up to 10 new Los Angeles permits from the last 7 days: at most $0.035 ($0.005 start + 10 x $0.003). `maxItems` is per city.

### Why use this building permit scraper?

- **10 cities, 1 schema.** LA, NYC (DOB NOW), Chicago, San Francisco, Austin, Seattle, Cincinnati, Mesa, Baton Rouge and Marin County all come out in the same fields.
- **Lead filters.** Filter by keyword (pool, solar, ADU, roof, demolition...), minimum project valuation, and days back.
- **Contractor & owner names** where the city publishes them (NYC and Chicago: ~97–100%, Austin contractors 91% with phone numbers).
- **Fast and cheap.** About 9,500 permits across 10 cities in under a minute.
- **Schedule it** daily or weekly to get a fresh lead list in your inbox, Google Sheets or CRM.

### Input

| Field | Description |
|---|---|
| `cities` | `los-angeles`, `new-york`, `chicago`, `san-francisco`, `austin`, `seattle`, `cincinnati`, `mesa`, `baton-rouge`, `marin-county` |
| `daysBack` | Permits issued in the last N days (default 7) |
| `keywords` | Match any keyword in permit type or description (e.g. `["solar","pool"]`) |
| `minValuation` | Minimum declared job value in USD |
| `maxItems` | Max results per city |

### Output example

```json
{ "city": "new-york", "permitNumber": "X01472603-I1-PL", "issueDate": "2026-10-14T00:00:00.000",
  "permitType": "Plumbing", "workDescription": "...", "address": "2234 ADAMS PLACE Bronx", "zip": "10457",
  "valuation": 25000, "status": "Permit Issued", "contractorName": "ACME PLUMBING INC", "contractorLicense": "MP 1234",
  "ownerName": "...", "lat": 40.85, "lon": -73.88, "sourceUrl": "https://data.cityofnewyork.us/d/rbx6-tga4" }
```

### Field coverage (test run, Oct 2026)

| City | Valuation | Contractor | Owner |
|---|---|---|---|
| New York | 100% | 100% | 99% |
| Chicago | 86% | 97% | 97% |
| Los Angeles | 100% | – | – |
| Austin | 24% | 91% (plus phone 90%) | – |
| San Francisco | 100% | – | – |
| Cincinnati | 94% | 99% | – |
| Mesa, AZ | 81% | 45% | – |
| Baton Rouge (lags ~1 wk) | 73% | 69% | – |
| Marin County | 95% | – | – |
| Seattle | 100% | 9% | – |

### Pricing

**$0.003 per permit** returned ($3 per 1,000), plus a **$0.005 run start** fee. You pay only for the permits you get.

### Use cases

Construction lead generation · solar installer leads · pool builder leads · roofing leads · contractor market research · real-estate development tracking · building-supply sales prospecting.

### Legal

Every record comes from an official government open-data portal. Use contact data in line with applicable laws (for example, CAN-SPAM and TCPA) when you do outreach.

### FAQ

**How fresh is the data?** About as fresh as each city's portal, which usually updates daily. LA updates weekly.
**Can you add my city?** Open an issue. More Socrata/ArcGIS cities are planned.

### Scheduled alerts and only-new mode

- **`onlyNew: true`** remembers what earlier runs returned (stored in your own Apify account) and returns **only new records**, so a daily or hourly schedule charges you only for fresh data.
- **`webhookUrl`** POSTs every new batch as JSON with a ready-to-post `text` and `content` summary. It works with Slack and Discord incoming webhooks, Zapier, Make and n8n.

### Use from AI agents and code

- **Apify MCP server:** add `johto.data/us-city-building-permits-leads` as a tool. Every input field is documented in the input schema.
- **REST, one call, returns JSON:**

```bash
curl -X POST "https://api.apify.com/v2/acts/johto.data~us-city-building-permits-leads/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H 'Content-Type: application/json' -d '{"maxItems": 50, "onlyNew": true}'
```

- **Python:** `ApifyClient(token).actor("johto.data/us-city-building-permits-leads").call(run_input={...})`

# Actor input Schema

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

City slugs to pull, e.g. \["los-angeles","new-york","chicago","san-francisco","austin","seattle"].

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

Only permits issued within this many days.

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

Match in permit type or work description, e.g. \["solar","roof","pool","ADU","demolition"]. Empty = all permits.

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

Skip permits below this declared job value (where the city reports one).

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

Maximum permits per city; each is one charged result ($0.003). Default 10 keeps an empty-input call a cheap sample; raise it for the full list.

## `onlyNew` (type: `boolean`):

Remember results across runs (per account) and return only items not seen before. Ideal for scheduled runs: you pay only for new records.

## `webhookUrl` (type: `string`):

Optional. POSTs the new items as JSON with a 'text'/'content' summary (Slack, Discord, Zapier, Make, n8n compatible).

## Actor input object example

```json
{
  "cities": [
    "los-angeles",
    "new-york",
    "chicago"
  ],
  "daysBack": 7,
  "keywords": [
    "solar"
  ],
  "minValuation": 0,
  "maxItems": 10,
  "onlyNew": false
}
```

# Actor output Schema

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

All building permit records from the run (one item per permit).

# 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": [
        "los-angeles",
        "new-york",
        "chicago"
    ],
    "keywords": [
        "solar"
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("johto.data/us-city-building-permits-leads").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": [
        "los-angeles",
        "new-york",
        "chicago",
    ],
    "keywords": ["solar"],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("johto.data/us-city-building-permits-leads").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": [
    "los-angeles",
    "new-york",
    "chicago"
  ],
  "keywords": [
    "solar"
  ],
  "maxItems": 10
}' |
apify call johto.data/us-city-building-permits-leads --silent --output-dataset

```

## MCP server setup

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

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/N2w9fCZEE5CPUf7wd/builds/zxiLenX9SloGkAWfO/openapi.json
