# US Building Permits – 93 Cities, Contractor/Construction Leads (`exuberantly_inventiveness/us-building-permits`) Actor

Building permit data from 93 US cities & counties in one clean table: new construction, roofing, solar, HVAC & remodel permits with contractor, valuation, ZIP & coordinates. Construction leads from official open data, no logins.

- **URL**: https://apify.com/exuberantly_inventiveness/us-building-permits.md
- **Developed by:** [justin cruz](https://apify.com/exuberantly_inventiveness) (community)
- **Categories:** Lead generation, Real estate, Business
- **Security:** Limited permissions
- **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

## US Building Permits Data – 93 Cities & Counties, Contractor & Construction Leads

**Fresh building permit data from 93 US cities, counties and states in one clean table – with the work type, trade, residential/commercial class, contractor, ZIP and coordinates already filled in.** Find roofing, window, solar, HVAC and remodel jobs the week they are permitted, see which contractors are busiest in your area, or track construction activity by ZIP.

**What it does:** queries 122 official government open-data feeds in 27 states + Washington, DC, and returns one normalized row per permit. **Who it's for:** contractors and installers looking for leads, building-material suppliers, real-estate investors and market researchers. **Why:** every city publishes permits differently; this Actor gives you one schema, one set of filters and an optional "only new / only changed since last run" feed, without logins or scraping private portals.

**Measured, not promised** (test run over permits issued 2026-10-26 to 2026-11-01, all sources): **33,811 permits** from 81 jurisdictions that had activity that week; 96.4 % have a ZIP, 87.8 % coordinates, 91.3 % a specific work category, 79.7 % a residential/commercial class and 42.8 % a contractor name. The whole run took about 2–5 minutes (4.4 minutes on the Apify platform).

### What one week looks like (real numbers)

Permits issued Oct 26 – Nov 1, 2026 in five big cities (run on Nov 3, 2026):

| City | Permits | New construction | Roofing | HVAC | Solar | Demolition |
|---|---:|---:|---:|---:|---:|---:|
| Los Angeles | 3,418 | 167 | 352 | 895 | 5 | 38 |
| New York City | 2,968 | 120 | 74 | 360 | 106 | 82 |
| Austin | 1,370 | 153 | 10 | 269 | 1 | 40 |
| Seattle | 887 | 38 | 2 | 244 | 0 | 12 |
| Chicago | 583 | 82 | 44 | 13 | 24 | 19 |
| **Total** | **9,226** | **560** | **482** | **1,781** | **136** | **191** |

59 % of those permits name a contractor, 99.9 % have a ZIP and 97 % have coordinates. At $5 per 1,000 permits, the whole week for these five cities costs about $46; a filtered list (for example only residential roofing in LA: 341 permits) costs about $1.70.

### Sample output (CSV preview)

Real rows from that week (selected columns; the full record is shown further down):

| city | permit_number | issue_date | category | property_class | description | zip | valuation | contractor_normalized |
|---|---|---|---|---|---|---|---:|---|
| Chicago, IL | B200517115 | 2026-10-27 | solar | residential | INSTALL SOLAR PANELS ON ROOF OF PRINCIPAL BUILDING… | 60620 | 14006 | Sunrun Installation Services |
| Seattle, WA | 7164089-ME | 2026-10-27 | hvac | commercial | FURNISH AND INSTALL (3) NEW VAV BOXES AND ASSOCIATED DUCTWORK… | 98101 | 48790 | Macdonald Miller Facility Solutions |
| Seattle, WA | 7169407-BP | 2026-10-27 | hvac | residential | BOILER REPLACEMENT | 98108 | 15475 | Carlson Mechanical |
| New York City, NY | B01325256-I1-GC | 2026-10-26 | new_construction | residential | PROPOSED NEW 7 STORY BUILDING WITH 26 RESIDENTIAL UNITS… | 11230 | | Brookstone Developers |

### Coverage at a glance

**AZ** Eloy, Maricopa County, Mesa, Scottsdale, Tempe, Tucson · **CA** Atascadero, Campbell, Citrus Heights, Corona, Los Angeles, Marin County, Placentia, Sacramento County, San Diego County, San Francisco, San Jose · **CO** Boulder, Denver, Douglas County · **DC** Washington · **FL** Alachua County, Broward County, Miami, Miami-Dade County, Orlando, Port St. Lucie, Weston · **ID** Boise · **IL** Chicago, Cook County (demolition), Rockford, Wheaton · **KS** Overland Park · **KY** Louisville · **LA** Baton Rouge, New Orleans · **MA** Boston, Cambridge, Somerville, Worcester · **MD** Baltimore, Baltimore County, Montgomery County · **MI** Detroit · **MN** Minneapolis · **MO** Kansas City, Raymore · **NC** Brunswick County, Cary, Charlotte/Mecklenburg, Greensboro, Raleigh, Wake County · **NJ** statewide · **NV** Henderson · **NY** New York City · **OH** Cincinnati, Cleveland, Columbus · **OR** Bend, Portland, Salem · **PA** Philadelphia, Pittsburgh · **SC** Bluffton, Charleston · **TN** Memphis/Shelby County, Nashville · **TX** Austin, College Station, Collin County, Dallas, Fort Worth, San Antonio, San Marcos, Tyler · **VA** Arlington County, Charlottesville, Norfolk, Virginia Beach · **WA** Bellevue, Everett, Pierce County, Puyallup, Seattle, Tacoma.
Full table with source IDs, licenses and freshness: see **Supported sources** below.

### How to use it

1. Click **Try for free** (or **Start**). The form is prefilled with 5 big cities, the last 7 days and 100 results – that run takes under a minute.
2. Pick your **cities** (or "All supported cities") and a **date window** – leave dates empty for the last 7 days.
3. Optionally add **filters**: work category (e.g. roofing), trade, residential/commercial, job value, ZIP codes or a radius around your shop.
4. Set **Max results** to cap your cost, then run. Download the results as Excel, CSV or JSON, or connect them to Google Sheets, Zapier, Make or your CRM.
5. For a lead feed, **schedule** it daily or weekly with *Only new permits* switched on so each run returns only permits you haven't seen.

### Why this Actor

- **Breadth:** 93 jurisdictions, including big cities (NYC, LA, Chicago, Dallas, Seattle, Philadelphia…), fast-growing suburbs/counties and statewide New Jersey. Every source passed a freshness check (newest record within 30 days) on 2026-11-03.
- **Only new permits, or status changes (incremental modes):** schedule it daily or weekly and get *only permits you have not seen before* (`new`), *only permits whose status changed* since the last run (`changes`, e.g. "In review" → "Issued", with `previous_status` and `changed_at`), or both (`new_and_changes`). The first run just records what exists (outputs and charges nothing).
- **Enrichment on every record:** `category` (new construction, addition, alteration/remodel, roofing, windows/doors, siding, HVAC, electrical, plumbing, solar, demolition, pool, fence, sign, other), `trades[]` + primary `trade`, `property_class` (residential / commercial / mixed) with `property_class_basis` (which signal decided it: occupancy field, permit type, description, address unit, zoning, contractor or valuation), `is_new_construction`, `status_std`, cleaned `valuation`, and `contractor_normalized` (in the test week "SUNRUN INSTALLATION SVC" in NYC, "SUNRUN INSTALLATION SERVICES INC" in Chicago and "Sunrun Installation Services" in Rockford all become `Sunrun Installation Services`).
- **ZIP + coordinates filled in:** a missing ZIP is taken from the address or derived offline from the coordinates (US Census ZCTA boundaries, 96.4 % agreement with the ZIP the city publishes, tested on 18,409 permits). Missing coordinates are geocoded with the **free US Census Bureau geocoder** (exact matches only). `zip_source` / `geo_source` tell you where each value came from.
- **Real filters:** category, trade, status, residential/commercial, valuation range, ZIP list (or 3-digit prefixes), **radius around a point**, states, keywords, contractor-present.
- **Reliable:** per-source timeouts and retries; a source that fails is skipped (the rest of the run continues) and reported in `RUN_STATS` with `error` / `stale` flags.
- **Analyst extras:** per-city `SUMMARY` (JSON + CSV) with counts by category/status, total and average valuation and top contractors (grouped by normalized name, with the sources and name variants each covers); optional summary rows in the dataset; CSV-friendly flat output.

### Use cases

| Who | What they pull | Suggested input |
|---|---|---|
| **Roofers, window/siding and remodel contractors** | New residential exterior jobs near the shop, every morning | `categories: ["roofing","windows_doors","siding"]`, `propertyClass: "residential"`, radius 30 mi, `incremental: true` |
| **Solar, HVAC, electrical and plumbing installers** | Trade permits pulled by competitors, by ZIP | `trades: ["solar"]` (or `hvac`, `electrical`, `plumbing`), `zipCodes` |
| **Building-material suppliers and distributors** | Which contractors are most active where, for sales prospecting | `onlyWithContractor: true`, then `SUMMARY.top_contractors` |
| **Real estate investors and developers** | New-construction and demolition activity by ZIP, as a leading indicator | `newConstructionOnly: true` or `categories: ["demolition"]` |
| **Market researchers, analysts and journalists** | Permit counts and valuations by city, category and month | `cities: ["all"]`, monthly `dateFrom`/`dateTo`, `SUMMARY.csv` |
| **Proptech and data teams** | A normalized feed instead of 116 different city APIs | API or scheduled runs into your warehouse, `flatOutput: true` |

### For AI assistants

Set `"mode": "agent"` to use every filter and get a machine-readable coverage record. Permits come first in the dataset; the last item is a `record_type: "coverage"` record (not charged), also saved in the key-value store as `COVERAGE`. Each queried jurisdiction gets a `status`: `completed` (ran, returned ≥1 permit), `no_match` (ran, 0 permits matched), or `failed` (source error or timeout, see `error`). Jurisdictions not queried are listed under `skipped` with a reason. Counts are only what the official sources returned; nothing is estimated.

Example input:

```json
{ "mode": "agent", "cities": ["seattle", "denver", "nowhere_city", "chicago"], "states": ["WA", "CO"],
  "trades": ["solar"], "dateFrom": "2026-10-01", "dateTo": "2026-11-01", "maxItems": 25 }
```

Coverage item from that run (shortened, real test output):

```json
{ "record_type": "coverage", "mode": "agent", "run_status": "completed", "total_results": 25, "limit_reached": true,
  "jurisdictions_queried": 2, "completed_count": 1, "no_match_count": 1, "failed_count": 0,
  "queried": [
    { "source_id": "seattle", "state": "WA", "status": "completed", "result_count": 25, "truncated_by_limit": true, "error": null },
    { "source_id": "denver", "state": "CO", "status": "no_match", "result_count": 0, "truncated_by_limit": false, "error": null } ],
  "skipped": [
    { "source_id": "nowhere_city", "reason": "unknown jurisdiction id (not one of the supported sources)" },
    { "source_id": "chicago", "reason": "not in selected states (WA, CO)" } ] }
```

If the input itself is invalid (e.g. `dateFrom` after `dateTo`), agent mode still writes a coverage record with `run_status: "failed"` and the `error`, then the run fails. Human mode (the default, and any input without `mode`) behaves exactly as before.

### Input examples

**Weekly lead list: residential exterior work within 40 miles of Chicago, $5k–$100k**

```json
{
  "cities": ["all"],
  "lastNDays": 7,
  "categories": ["roofing", "windows_doors", "siding"],
  "propertyClass": "residential",
  "minValuation": 5000,
  "maxValuation": 100000,
  "centerLat": "41.8781", "centerLon": "-87.6298", "radiusMiles": 40
}
```

**Scheduled monitoring – only new permits each day**

```json
{
  "cities": ["austin", "dallas", "san_antonio"],
  "lastNDays": 10,
  "incremental": true,
  "incrementalStateKey": "texas-daily",
  "trades": ["hvac", "electrical"]
}
```

Create a [schedule](https://docs.apify.com/platform/schedules) (e.g. every morning) with this input. Run 1 records the current permits and outputs nothing. Every later run outputs only permits that were not returned before. Use a look-back (`lastNDays`) a bit longer than the schedule interval, because some cities post permits a few days late; already-seen permits are never returned twice. In our test, run 1 (Oct 26–29) recorded 2,974 permits and output 0; run 2 (Oct 26–Nov 1) output only the 776 new permits (all dated Oct 30–Nov 1); run 3 with the same input output 0.

**Daily status-change feed (permits that moved from review to issued, finaled, expired…)**

```json
{
  "cities": ["kansas_city_mo", "charlottesville"],
  "lastNDays": 60,
  "incremental": true,
  "incrementalMode": "changes",
  "incrementalStateKey": "status-watch"
}
```

Run 1 stores each permit's current status and outputs nothing. Later runs output only permits whose `status` differs from the stored one, with `change_type: "status_changed"`, `previous_status`, `previous_status_std` and `changed_at` (the run date the change was detected). `new_and_changes` combines both feeds (`change_type` is `new` or `status_changed`). Use a long look-back for `changes`, since a status can change weeks after issue. Older incremental state from v1.2 keeps working.

**By ZIP, flat CSV output with per-city summary rows**

```json
{ "cities": ["chicago", "los_angeles"], "dateFrom": "2026-10-01", "dateTo": "2026-10-31", "zipCodes": ["606", "90026"], "flatOutput": true, "pushSummaryRecords": true }
```

If you leave out the dates, the run covers the last 7 days. `cities: ["all"]` queries every source; with `states` you can limit it to some states.

### Output example (real record from a test run)

```json
{
  "record_type": "permit",
  "source_id": "brunswick_county_nc",
  "city": "Brunswick County",
  "state": "NC",
  "permit_number": "693780-1006",
  "issue_date": "2026-10-30",
  "application_date": null,
  "status": "Active",
  "permit_type": "Commercial - ELECTRICAL",
  "work_class": "Trades",
  "description": "Elect per code/pool",
  "address": "7310 WILBUR MCKEITHAN WAY NE",
  "zip": "28451",
  "lat": 34.18943706,
  "lon": -78.08322261,
  "valuation": 349351,
  "contractor_name": "REEVES ELECTRIC",
  "contractor_license": null,
  "source_url": "https://www.brunswickcountync.gov/",
  "data_source": "ArcGIS: https://services1.arcgis.com/W6gamXPYQeLXrdAd/arcgis/rest/services/Permit_Locations/FeatureServer/0",
  "date_basis": "issued",
  "category": "electrical",
  "trades": ["electrical", "pool"],
  "trade": "electrical",
  "property_class": "commercial",
  "property_class_basis": "permit_type",
  "is_new_construction": false,
  "status_std": "issued",
  "contractor_normalized": "Reeves Electric",
  "zip_source": "source",
  "geo_source": "source"
}
```

Other fields: `distance_miles` (radius searches), `raw` (optional, sanitized source row), and in change modes `change_type`, `previous_status`, `previous_status_std`, `changed_at`. Dataset views: **Permits**, **Contractor leads**, **Locations**, **Status changes**. Download as JSON, CSV, Excel or XML.

Key-value store outputs: `SUMMARY` / `SUMMARY.csv` (per city), `RUN_STATS` (per-source scanned / matched / pushed counts, newest date seen, `stale`, `error`, geocoder use, incremental state) and contractor stats (unique raw vs normalized names, multi-source contractors, top contractors).

### Supported sources (93)

Permit counts are from the local test run over issue dates 2026-10-26..2026-11-01 (33,811 permits) and change week to week. A 0 means the source published nothing with an issue date in that week (it was still fresh within 30 days; Tyler, TX publishes about monthly).

| ID | City / county | Portal | License / terms | Permits issued 2026-10-26..11-01 | Newest issue date (health check 2026-11-03) |
|---|---|---|---|---:|---|
| `eloy` | Eloy, AZ | ArcGIS | [City of Eloy open GIS data](https://services7.arcgis.com/VfOwt1fngp5cVBlk/arcgis/rest/services/Permits/FeatureServer) | 1 | 2026-10-28 |
| `maricopa_county` | Maricopa County (unincorporated), AZ | ArcGIS | [Maricopa County GIS open data terms](https://data-maricopa.opendata.arcgis.com/) | 162 | 2026-10-30 |
| `mesa` | Mesa, AZ | Socrata | [City of Mesa Open Data terms](https://citydata.mesaaz.gov/d/dzpk-hxfb) | 89 | 2026-11-01 |
| `scottsdale` | Scottsdale, AZ | ArcGIS | [City of Scottsdale open data](https://data.scottsdaleaz.gov/) | 5 | 2026-10-30 |
| `tempe` | Tempe, AZ | ArcGIS | [City of Tempe Open Data (CC BY 4.0)](https://data.tempe.gov/) | 64 | 2026-10-30 |
| `tucson` | Tucson, AZ | ArcGIS | [City of Tucson open data](https://gisdata.tucsonaz.gov/) | 174 | 2026-11-01 |
| `atascadero` | Atascadero, CA | ArcGIS | [City of Atascadero open GIS data](https://services2.arcgis.com/N2rywTnpbBhelXvy/arcgis/rest/services/Permits_public/FeatureServer) | 23 | 2026-10-30 |
| `campbell` | Campbell, CA | ArcGIS | [City of Campbell open GIS data](https://www.arcgis.com/home/item.html?id=CampbellPermits) | 45 | 2026-10-30 |
| `citrus_heights` | Citrus Heights, CA | ArcGIS | [City of Citrus Heights open data](https://services8.arcgis.com/F2vUxnlx169smga0/arcgis/rest/services/BuildingPermitsIssued/FeatureServer) | 131 | 2026-11-02 |
| `corona` | Corona, CA | Socrata | [City of Corona CorStat open data](https://corstat.coronaca.gov/d/2agx-camz) | 0 | 2026-10-15 |
| `los_angeles_county_rebuild` | Los Angeles County (fire rebuild), CA | ArcGIS | [LA County Public Works open GIS data (EPIC-LA)](https://services.arcgis.com/RmCCgQtiZLDCtblq/arcgis/rest/services/Rebuild_Permits_Issued_DEV/FeatureServer/0) | 54 | 2026-11-02 |
| `los_angeles` | Los Angeles, CA | Socrata | [LA Open Data Terms of Use](https://data.lacity.org/stories/s/Terms-of-Use/2b5n-6nxp) | 3418 | 2026-10-31 |
| `marin_county` | Marin County, CA | Socrata | [Open Data Commons ODbL](https://data.marincounty.gov/d/mkbn-caye) | 75 | 2026-11-01 |
| `placentia` | Placentia, CA | ArcGIS | [City of Placentia open data](https://www.placentia.org/) | 0 | 2026-10-21 |
| `sacramento_county` | Sacramento County (unincorporated), CA | ArcGIS | [Sacramento County open data](https://data.saccounty.gov/) | 572 | 2026-10-31 |
| `san_diego_county` | San Diego County (unincorporated), CA | Socrata | [County of San Diego Open Data Terms](https://data.sandiegocounty.gov/d/red2-qccu) | 188 | 2026-11-01 |
| `san_francisco` | San Francisco, CA | Socrata | [DataSF Open Data (PDDL)](https://datasf.org/opendata/terms-of-use/) | 334 | 2026-10-30 |
| `san_jose` | San Jose, CA | CKAN | [Creative Commons Zero (CC0)](https://data.sanjoseca.gov/dataset/building-permits) | 504 | 2026-10-31 |
| `boulder` | Boulder, CO | ArcGIS | [City of Boulder Open Data terms](https://open-data.bouldercolorado.gov/) | 179 | 2026-10-30 |
| `denver` | Denver, CO | ArcGIS | [Denver Open Data (CC BY 3.0)](https://opendata-geospatialdenver.hub.arcgis.com/) | 140 | 2026-10-31 |
| `douglas_county_co` | Douglas County, CO | ArcGIS | [Douglas County open data](https://data-douglas.opendata.arcgis.com/) | 202 | 2026-10-30 |
| `washington_dc` | Washington, DC | ArcGIS | [Open Data DC (CC BY 4.0)](https://opendata.dc.gov/pages/terms-of-use) | 841 | 2026-10-29 |
| `alachua_county` | Alachua County (unincorporated), FL | ArcGIS | [Alachua County open data](https://data-alachuacounty.opendata.arcgis.com/) | 205 | 2026-11-02 |
| `broward_county` | Broward County (unincorporated), FL | ArcGIS | [Broward County GIS open data](https://geohub-bcgis.opendata.arcgis.com/) | 10 | 2026-10-29 |
| `miami` | Miami, FL | ArcGIS | [City of Miami Open Data terms](https://datahub-miamigis.opendata.arcgis.com/) | 624 | 2026-11-01 |
| `miami_dade_county` | Miami-Dade County, FL | ArcGIS | [Miami-Dade County Open Data terms](https://gis-mdc.opendata.arcgis.com/) | 1451 | 2026-11-01 |
| `orlando` | Orlando, FL | Socrata | [City of Orlando Open Data Terms](https://data.cityoforlando.net/) | 586 | 2026-11-02 |
| `port_st_lucie` | Port St. Lucie, FL | ArcGIS | [City of Port St. Lucie open GIS data](https://services1.arcgis.com/YdUP5V6WwzeG8T8r/arcgis/rest/services/Permits/FeatureServer) | 491 | 2026-10-31 |
| `weston` | Weston, FL | ArcGIS | [City of Weston open GIS data](https://portal.westonfl.org/arcgis/rest/services/Accela/IssuedPermitReport/FeatureServer) | 72 | 2026-10-30 |
| `atlanta` | Atlanta, GA | ArcGIS | [City of Atlanta open GIS data (Accela building permits)](https://services5.arcgis.com/5RxyIIJ9boPdptdo/arcgis/rest/services/building_permit_featureLayer/FeatureServer/0) | 212 | 2026-10-29 |
| `boise` | Boise (high-impact, new housing & demolition permits), ID | ArcGIS | [City of Boise open data](https://opendata.cityofboise.org/) | 2 | 2026-10-30 |
| `chicago` | Chicago, IL | Socrata | [City of Chicago Data Portal Terms of Use](https://www.chicago.gov/city/en/narr/foia/data_disclaimer.html) | 583 | 2026-11-01 |
| `cook_county_demolition` | Cook County (suburban asbestos & demolition permits), IL | Socrata | [Public Domain (Cook County Open Data)](https://datacatalog.cookcountyil.gov/d/gpmj-6p9q) | 100 | 2026-11-02 |
| `rockford_il` | Rockford, IL | Socrata | [Illinois EDP open data (City of Rockford)](https://illinois-edp.data.socrata.com/d/3k8p-pkx8) | 230 | 2026-10-31 |
| `st_charles_il` | St. Charles, IL | ArcGIS | [City of St. Charles, IL open GIS data](https://services6.arcgis.com/K7950S4bDbtsSspe/arcgis/rest/services/StCharlesPermitData/FeatureServer/0) | 47 | 2026-11-02 |
| `wheaton` | Wheaton, IL | ArcGIS | [City of Wheaton open data](https://www.wheaton.il.us/) | 0 | 2026-10-22 |
| `overland_park` | Overland Park, KS | ArcGIS | [City of Overland Park open data](https://opkansas.org/) | 65 | 2026-10-29 |
| `louisville` | Louisville (Metro), KY | ArcGIS | [Louisville Metro Open Data terms](https://data.louisvilleky.gov/) | 333 | 2026-11-02 |
| `baton_rouge` | Baton Rouge (East Baton Rouge Parish), LA | Socrata | [Public Domain](https://data.brla.gov/) | 159 | 2026-10-30 |
| `new_orleans` | New Orleans, LA | Socrata | [CC0 1.0 (Public Domain Dedication)](https://data.nola.gov/) | 321 | 2026-11-02 |
| `boston` | Boston, MA | CKAN | [Open Data Commons PDDL](https://data.boston.gov/dataset/approved-building-permits) | 819 | 2026-11-02 |
| `cambridge_ma` | Cambridge, MA | Socrata | [ODC Public Domain Dedication and License](https://data.cambridgema.gov/) | 122 | 2026-10-31 |
| `somerville` | Somerville, MA | Socrata | [Open Data Commons ODbL](https://data.somervillema.gov/d/nneb-s3f7) | 121 | 2026-10-29 |
| `worcester` | Worcester, MA | ArcGIS | [City of Worcester open data](https://opendata.worcesterma.gov/) | 378 | 2026-10-31 |
| `baltimore_county_md` | Baltimore County, MD | ArcGIS | [Baltimore County Government open GIS data](https://bcgisdata.baltimorecountymd.gov/arcgis/rest/services/DevelopmentManagement/ActiveDevelopment/MapServer) | 193 | 2026-11-02 |
| `baltimore` | Baltimore, MD | ArcGIS | [Open Baltimore terms](https://data.baltimorecity.gov/) | 650 | 2026-11-01 |
| `montgomery_county_md` | Montgomery County, MD | Socrata | [Public Domain](https://data.montgomerycountymd.gov/) | 325 | 2026-10-28 |
| `detroit` | Detroit, MI | ArcGIS | [Detroit Open Data Portal terms](https://data.detroitmi.gov/) | 485 | 2026-11-01 |
| `minneapolis` | Minneapolis, MN | ArcGIS | [Open Minneapolis terms](https://opendata.minneapolismn.gov/) | 945 | 2026-11-01 |
| `kansas_city_mo` | Kansas City, MO | Socrata | [City of Kansas City, MO Open Data terms of use](https://data.kcmo.org/d/w8jz-wjgn) | 876 | 2026-11-02 |
| `raymore` | Raymore, MO | ArcGIS | [City of Raymore open data](https://www.raymore.com/) | 54 | 2026-10-30 |
| `brunswick_county_nc` | Brunswick County, NC | ArcGIS | [Brunswick County open data](https://www.brunswickcountync.gov/) | 810 | 2026-10-30 |
| `cary` | Cary, NC | OpenDataSoft | [CC0 1.0 Universal](https://data.townofcary.org/explore/dataset/permit-applications/) | 185 | 2026-10-30 |
| `charlotte` | Charlotte / Mecklenburg County, NC | ArcGIS | [Mecklenburg County open GIS data](https://maps.mecknc.gov/opendata) | 754 | 2026-11-01 |
| `greensboro` | Greensboro, NC | ArcGIS | [City of Greensboro open GIS data](https://data.greensboro-nc.gov/) | 77 | 2026-11-02 |
| `raleigh` | Raleigh, NC | ArcGIS | [City of Raleigh Open Data terms](https://data-ral.opendata.arcgis.com/) | 146 | 2026-10-29 |
| `wake_county` | Wake County (unincorporated & contract towns), NC | ArcGIS | [Wake County open data](https://data-wake.opendata.arcgis.com/) | 109 | 2026-10-30 |
| `new_jersey` | New Jersey (statewide, municipality level), NJ | Socrata | [Public Domain (NJ DCA)](https://data.nj.gov/d/w9se-dmra) | 0 | 2026-10-19 |
| `henderson` | Henderson, NV | ArcGIS | [City of Henderson open data](https://maps.cityofhenderson.com/arcgis/rest/services/public/OpenDevPermits/MapServer) | 38 | 2026-10-29 |
| `new_york_city` | New York City, NY | Socrata | [NYC Open Data Terms of Use](https://www.nyc.gov/main/terms-of-use) | 2968 | 2026-10-30 |
| `cincinnati` | Cincinnati, OH | Socrata | [Public Domain](https://data.cincinnati-oh.gov/) | 201 | 2026-10-30 |
| `cleveland` | Cleveland, OH | ArcGIS | [City of Cleveland Open Data terms](https://data.clevelandohio.gov/) | 299 | 2026-10-31 |
| `columbus` | Columbus, OH | ArcGIS | [City of Columbus Open Data terms](https://opendata.columbus.gov/) | 898 | 2026-10-31 |
| `bend` | Bend, OR | ArcGIS | [City of Bend Open Data terms](https://data.bendoregon.gov/) | 109 | 2026-11-01 |
| `jackson_county_or` | Jackson County, OR | ArcGIS | [Jackson County, OR open GIS data](https://jcportal.jacksoncountyor.gov/server/rest/services/Property/Permits_Building/FeatureServer/1) | 76 | 2026-11-02 |
| `portland_or` | Portland, OR | ArcGIS | [City of Portland open data (PortlandMaps)](https://www.portlandmaps.com/od/rest/services/COP_OpenData_PlanningDevelopment/MapServer/126) | 2 | 2026-10-28 |
| `salem` | Salem, OR | ArcGIS | [City of Salem open data](https://data.cityofsalem.net/) | 24 | 2026-10-30 |
| `philadelphia` | Philadelphia, PA | CARTO | [OpenDataPhilly / City of Philadelphia terms](https://opendataphilly.org/datasets/licenses-and-inspections-building-permits/) | 964 | 2026-11-02 |
| `pittsburgh` | Pittsburgh, PA | CKAN | [WPRDC (CC BY 4.0 / ODC)](https://data.wprdc.org/dataset/pli-permits) | 175 | 2026-10-30 |
| `bluffton_sc` | Bluffton, SC | ArcGIS | [Town of Bluffton open GIS data](https://services2.arcgis.com/emqdvAOVfTSmahz0/arcgis/rest/services/Permits/FeatureServer) | 23 | 2026-10-30 |
| `charleston_sc` | Charleston (new construction only), SC | ArcGIS | [City of Charleston open data](https://data-charleston.opendata.arcgis.com/) | 0 | 2026-10-22 |
| `memphis` | Memphis / Shelby County, TN | ArcGIS | [Memphis Data Hub terms](https://data.memphistn.gov/) | 154 | 2026-10-30 |
| `nashville` | Nashville (Metro Davidson County), TN | ArcGIS | [Nashville Open Data terms](https://datanashvillegov-nashville.hub.arcgis.com/) | 208 | 2026-11-01 |
| `austin` | Austin, TX | Socrata | [Public Domain U.S. Government](https://data.austintexas.gov/stories/s/Terms-of-Use/rj3p-5kpt) | 1370 | 2026-11-01 |
| `college_station` | College Station, TX | Socrata | [City of College Station Open Data Terms](https://data.cstx.gov/d/hrbn-znt6) | 117 | 2026-10-30 |
| `collin_county` | Collin County (Collin CAD, all cities), TX | Socrata | [Texas Open Data Portal terms](https://data.texas.gov/d/82ee-gbj5) | 13 | 2026-10-31 |
| `dallas` | Dallas, TX | Socrata | [Dallas OpenData Terms of Use](https://www.dallasopendata.com/stories/s/Terms-of-Use/9xbj-ei8a) | 1499 | 2026-11-01 |
| `fort_worth` | Fort Worth, TX | ArcGIS | [City of Fort Worth open data terms](https://data.fortworthtexas.gov/) | 1109 | 2026-11-02 |
| `harris_county_tx` | Harris County (unincorporated), TX | ArcGIS | [Harris County Engineering open GIS data (ePermits)](https://www.gis.hctx.net/arcgishcpid/rest/services/Permits/ePermits/MapServer/1) | 696 | 2026-11-03 |
| `san_antonio` | San Antonio, TX | CKAN | [City of San Antonio Open Data terms](https://data.sanantonio.gov/dataset/building-permits) | 1300 | 2026-10-30 |
| `san_marcos` | San Marcos, TX | ArcGIS | [City of San Marcos open data](https://data-sanmarcostx.opendata.arcgis.com/) | 63 | 2026-10-31 |
| `tyler_tx` | Tyler, TX | ArcGIS | [City of Tyler open GIS data](https://services5.arcgis.com/RmXXW3PwBZGOxlSe/arcgis/rest/services/Permit_Data_With_XY/FeatureServer/0) | 0 | 2026-10-09 |
| `arlington_county_va` | Arlington County, VA | Arlington Open Data API | [Arlington County Open Data policy](https://data.arlingtonva.us/) | 304 | 2026-11-01 |
| `charlottesville` | Charlottesville, VA | ArcGIS | [City of Charlottesville open data](https://opendata.charlottesville.org/) | 82 | 2026-11-01 |
| `norfolk` | Norfolk, VA | Socrata | [Norfolk Open Data Terms of Use](https://data.norfolk.gov/) | 268 | 2026-11-01 |
| `virginia_beach` | Virginia Beach, VA | ArcGIS | [City of Virginia Beach Open Data terms](https://data.virginiabeach.gov/) | 584 | 2026-10-30 |
| `bellevue` | Bellevue, WA | ArcGIS | [City of Bellevue Open Data terms](https://data.bellevuewa.gov/) | 189 | 2026-11-01 |
| `edgewood_wa` | Edgewood, WA | ArcGIS | [City of Edgewood, WA open GIS data](https://services.arcgis.com/Vf718JZV3goJ8GJT/arcgis/rest/services/All_Permits/FeatureServer/0) | 3 | 2026-10-30 |
| `everett` | Everett, WA | Socrata | [City of Everett Open Data Terms](https://data.everettwa.gov/d/3w3u-656c) | 228 | 2026-10-30 |
| `pierce_county` | Pierce County (unincorporated), WA | Socrata | [Pierce County Open Data Terms](https://open.piercecountywa.gov/d/nhnt-v7ka) | 139 | 2026-10-28 |
| `puyallup` | Puyallup, WA | ArcGIS | [City of Puyallup open GIS data](https://services8.arcgis.com/5K6vnOH0GkPyJs6A/arcgis/rest/services/City_View/FeatureServer) | 29 | 2026-10-30 |
| `seattle` | Seattle, WA | Socrata | [Public Domain](https://data.seattle.gov/stories/s/Data-Policy/6ukr-wvzx) | 887 | 2026-10-31 |
| `tacoma` | Tacoma, WA | ArcGIS | [City of Tacoma open data](https://data.cityoftacoma.org/) | 139 | 2026-10-30 |

Some fields simply aren't published by some sources: for example Philadelphia, Maricopa County, Washington DC and Virginia Beach publish no valuation, and New Jersey publishes no street address (municipality and block/lot only, and its newest dates lag 2–4 weeks). Where a feed mixes company and private-person names in its contractor field, only business-looking names are returned. Missing values come back as `null`; nothing is invented. `date_basis` is `approved` for Cook County (approval date) and `issued` elsewhere.

### Pricing

You pay only for results: one charge per permit returned (event `permit-result`). **Price: $5 per 1,000 permits ($0.005 each)** – so the prefilled 100-permit example costs about $0.50, and a 1,000-permit weekly lead list about $5. The current price is always shown on the **Pricing** tab. There is no separate charge for compute or proxies.

- Summary rows and the first "record only" monitoring run are free.
- Set **Max results** and/or a **maximum cost per run** in the run options; the Actor stops cleanly at that limit, so you never pay more than you chose.
- Apify's free plan includes monthly platform credits you can use to try the Actor.

### Notes and limits

- Accuracy and freshness depend on each government feed. `source_url` links the original.
- Category, trade and property class are derived from the permit type and description text with rules, so they are very good but not perfect. `property_class` uses the source's occupancy/use field first, then permit type and description, then address unit, zoning, known residential installers and very large valuations; it is `null` when nothing gives a clear signal (20.3 % of records in the test week, down from 34.1 % in v1.2 on the same sources; most remaining blanks are NYC sidewalk sheds/scaffolds, San Antonio and Fort Worth trade permits and right-of-way work). The `propertyClass` filter drops those.
- Derived ZIPs (`zip_source: zcta_derived`) use Census ZIP Code Tabulation Areas, which approximate USPS ZIPs.
- `contractor_normalized` is a rules-based clean-up (case, punctuation, legal suffixes such as LLC/Inc. dropped, DBA, trailing license numbers, abbreviations such as Svc/Plbg/Elec, placeholders); some acronyms written in capitals may come out title-cased; it never merges different companies on fuzzy similarity, and personal-looking names are still dropped.
- Multi-row permits are deduplicated (one result per permit, date and filing).

### FAQ

**How fresh is the data?** Each run queries the government feeds live, so you get whatever the city has published at that moment. Most cities publish daily; some lag a few days, and New Jersey lags 2–4 weeks. On 2026-11-03 every one of the 87 sources had a record from the last 30 days. Each run's `RUN_STATS` record shows the newest date per source and flags stale sources.

**Which areas are covered?** The 93 jurisdictions in the table above. Coverage is limited to places that publish permits through a public open-data API, so many cities (and most rural counties) are not available. Some fields aren't published everywhere, for example valuation or contractor name – see "Notes and limits".

**Is this legal?** The Actor only reads official open-data APIs that governments publish for public reuse. It does not log in, bypass CAPTCHAs or scrape private portals. Each source has its own license (linked in the table); see "Data sources and attribution" below.

**Does it return personal data?** No owner, applicant, phone, email or staff fields are returned, and they are stripped even from the optional raw record. Contractor fields are limited to business names and license numbers; names that look like private individuals are dropped. If you combine this data with other sources, you are responsible for complying with privacy and marketing laws (e.g. CAN-SPAM, TCPA, CCPA).

**Why are some fields empty?** If a city doesn't publish a value, it comes back as `null` – nothing is guessed or invented. Derived values (category, trade, property class, derived ZIP, geocoded coordinates) are labeled in `property_class_basis`, `zip_source` and `geo_source`.

**How much does a typical run cost?** $5 per 1,000 permits returned. Examples from the Oct 26 – Nov 1, 2026 week: all of Chicago (583 permits) ≈ $2.90; all of Los Angeles (3,418) ≈ $17; LA residential roofing only (341) ≈ $1.70. Filters are applied before you are charged, so narrow filters cost less. Set **Max results** or a maximum cost per run to cap spend.

**Does it include homeowner names, phone numbers or emails?** No. You get the permit, address, work description, valuation and the contractor's business name (where the city publishes it). Owner and applicant fields are removed.

**What counts as "new construction"?** `is_new_construction` is `true` when the permit's `category` is `new_construction`, which the rules assign from the permit type, work class and description (for example "New Construction of a 2-Story Single Family Res."); additions and remodels have their own categories. In the sample week, 560 of 9,226 permits in five big cities were new construction.

**Can I get only new permits every day?** Yes: schedule the Actor with `incremental: true`. Each run returns only permits it hasn't returned before, so a daily schedule is a daily lead list.

**How do I get the data into Google Sheets, a CRM or my own code?** Download as CSV/Excel/JSON from the run, use Apify's Google Sheets, Zapier or Make integrations, or call the Actor from the [Apify API](https://docs.apify.com/api/v2) / Python and JavaScript clients and read the dataset.

**How is this different from scraping a city permit portal?** It doesn't touch Accela/EnerGov web portals or log in anywhere; it reads the official open-data APIs (Socrata, ArcGIS, CKAN, CARTO, OpenDataSoft), so runs are fast (a week of 5 big cities takes well under a minute) and don't break when a portal redesigns.

**Can you add my city?** Open an issue on the **Issues** tab with the city name and, if you know it, the link to its open-data permit dataset. Only sources with a public open-data API can be added.

### Data sources and attribution

Data is provided by the cities, counties and states listed in the table above, under each publisher's open-data license or terms of use (linked per source). Every record includes `data_source` (portal and dataset id) and `source_url` (the original record or dataset) for attribution. Some sources require attribution when you republish the data, for example **CC BY** (Tempe, Denver, Washington DC, Pittsburgh/WPRDC) and **ODbL** (Marin County, Somerville, which also requires share-alike for databases built from it). If you republish, credit the publisher, e.g. "Source: City of Denver Open Data, CC BY 3.0", and follow the linked terms. This Actor is not affiliated with or endorsed by any government agency.

### Disclaimer

Permit data is provided "as is" from public sources and may be incomplete, delayed or contain errors made by the publisher. Derived fields (category, trade, property class, normalized contractor name, derived ZIP, geocoded coordinates) are produced by rules and can be wrong. A permit is evidence of a project, not an exclusive lead or a promise of work. Verify important details with the issuing agency before relying on them.

### Support

Questions, a broken source or a city you'd like added? Open an issue on the **Issues** tab of this Actor.

### Changelog

- **1.6** (Nov 2026) – Two input modes. Human mode (default): simpler form (place, permit type/trade, dates, max results) with advanced options in collapsed sections. AI/Agent mode (`"mode": "agent"`): coverage record (`COVERAGE`) with per-jurisdiction status codes `completed` / `no_match` / `failed` and skipped reasons. Existing inputs, output fields and pricing are unchanged.
- **1.5** (Nov 2026) – 6 new sources (93 total): Atlanta GA, Harris County TX (unincorporated), St. Charles IL, Jackson County OR, Edgewood WA, LA County fire-rebuild permits. Week counts for the new rows are from a 2026-11-04 test of the same week.
- **1.4.6** – README: one-week sample numbers, CSV preview, coverage by state, more FAQ. No code changes.
- **1.4.5** – Added an Actor output schema (Output tab links to permits, contractor leads, per-source summary and run stats).
- **1.3** (Nov 2026) – 87 sources (116 datasets) in 26 states + DC; status-change monitoring (`changes`, `new_and_changes`); better residential/commercial classification; consistent normalized contractor names; offline ZIP derivation from coordinates; null-like text values ("NA", "None") cleaned to `null`; simpler input form with a quick prefilled example.
- **1.2** (Nov 2026) – Expanded coverage and enrichment (more cities, normalized contractor names, location filters).
- **1.0** (Nov 2026) – First version: 22 cities in one normalized schema.

# Actor input Schema

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

Human mode: pick a place, work type and dates. AI/Agent mode ("mode": "agent") accepts every field below and also writes a coverage record (jurisdictions queried, result count per jurisdiction, skipped ones and why, status completed / no_match / failed) to the key-value store as COVERAGE and as the last dataset item (not charged). All filters work in both modes; existing inputs without this field run unchanged.

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

Which official permit feeds to query. Pick "All supported cities" together with a state to get every source in that state.

## `states` (type: `array`):

Limit the run to sources in these states (combine with "All supported cities" to get every source in a state).

## `categories` (type: `array`):

Kind of work, e.g. new construction, roofing, solar. Empty = all types.

## `trades` (type: `array`):

Keep permits that involve any of these trades (a permit can have several). Empty = all.

## `lastNDays` (type: `integer`):

Last N days up to today (overrides the dates below). Leave at 0 and empty dates for the last 7 days.

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

First permit issue date to include. Defaults to 7 days ago.

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

Last permit issue date to include (inclusive). Defaults to today.

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

Stop after this many permits across all cities (you are charged per permit, so this also caps your cost). 0 = no limit. With several cities, results are taken round-robin so each city gets a share.

## `permitTypeKeywords` (type: `array`):

Keep only permits whose type, work class or description contains any of these words (case-insensitive), e.g. roof, window, addition, solar, new construction. Leave empty for all.

## `statusStd` (type: `array`):

Standardized status. Empty = all.

## `propertyClass` (type: `string`):

Residential / commercial (derived; permits whose class cannot be determined are dropped when set).

## `newConstructionOnly` (type: `boolean`):

Shortcut for category = new_construction.

## `onlyWithContractor` (type: `boolean`):

Drop permits that have no contractor/business name.

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

Skip permits below this job value. Permits with no valuation are dropped when this is > 0. Some sources (Philadelphia, Maricopa County, most new Dallas records) publish no valuation.

## `maxValuation` (type: `integer`):

Skip permits above this job value (0 = no maximum). Permits with no valuation are kept unless a minimum is set.

## `zipCodes` (type: `array`):

Keep only these ZIPs. 3-digit prefixes work too (e.g. 531). ZIPs missing from the source are filled from the address, the coordinates (Census ZCTA) or the geocoder first.

## `centerLat` (type: `string`):

e.g. 42.5847. Use with longitude and radius.

## `centerLon` (type: `string`):

e.g. -87.8212

## `radiusMiles` (type: `integer`):

Keep permits within this distance of the center. Permits without coordinates (after geocoding) are dropped. Sources far outside the circle are skipped entirely.

## `geocodeMissing` (type: `boolean`):

Fill lat/lon for permits that have an address but no coordinates using the free US Census Bureau geocoder (exact matches only).

## `maxGeocode` (type: `integer`):

Upper bound on geocoder lookups per run.

## `maxItemsPerCity` (type: `integer`):

Cap per city so one large city does not use up the whole run. 0 = no cap.

## `flatOutput` (type: `boolean`):

Write "trades" as a semicolon-separated string (and raw as JSON text) so CSV/Excel exports have one column per field.

## `pushSummaryRecords` (type: `boolean`):

Append one record_type="summary" row per city (counts by category/status, total valuation, top contractors). Summary rows are not charged. A summary is always saved as SUMMARY / SUMMARY.csv in the key-value store.

## `includeRaw` (type: `boolean`):

Add the original source row under "raw". Owner/applicant names, phones and emails are always removed.

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

Remember permits already returned (in the named key-value store "us-building-permits-state") and output only new ones on later runs. Ideal for a daily/weekly schedule with "last N days". Turned on automatically when "Incremental output" is a changes mode.

## `incrementalMode` (type: `string`):

What a monitoring run outputs. The Actor stores each permit's last status; a later run outputs permits whose status changed with `change_type: "status_changed"`, `previous_status` and `changed_at`. New permits get `change_type: "new"`. The first run of a state only records (outputs and charges nothing). Changes modes default to a 60-day look-back so older permits can be re-checked. "Only new permits" takes effect only when the switch above is on; the two changes modes turn monitoring on by themselves.

## `incrementalFirstRun` (type: `string`):

What the very first incremental run per source does. "seed" records the current permits without outputting (or charging) them, so the next run returns only new ones.

## `incrementalStateKey` (type: `string`):

Use different names to keep separate "already seen" lists for different schedules/filters.

## `sourceTimeoutSecs` (type: `integer`):

Skip a source that returns no data for this long, so one slow portal cannot stall the run.

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

Free token from any Socrata portal; raises rate limits for large runs.

## Actor input object example

```json
{
  "mode": "human",
  "cities": [
    "chicago",
    "los_angeles",
    "new_york_city",
    "austin",
    "seattle"
  ],
  "states": [],
  "categories": [],
  "trades": [],
  "lastNDays": 7,
  "maxItems": 100,
  "permitTypeKeywords": [],
  "statusStd": [],
  "propertyClass": "any",
  "newConstructionOnly": false,
  "onlyWithContractor": false,
  "minValuation": 0,
  "maxValuation": 0,
  "zipCodes": [],
  "radiusMiles": 0,
  "geocodeMissing": true,
  "maxGeocode": 10000,
  "maxItemsPerCity": 0,
  "flatOutput": false,
  "pushSummaryRecords": false,
  "includeRaw": false,
  "incremental": false,
  "incrementalMode": "new",
  "incrementalFirstRun": "seed",
  "incrementalStateKey": "default",
  "sourceTimeoutSecs": 120
}
```

# Actor output Schema

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

All permit records returned by the run (one item per permit), opened in the Overview view.

## `contractorLeads` (type: `string`):

Same permits in the Leads view: contractor, trade, value and contact-ready fields.

## `summary` (type: `string`):

One row per city/county source with permit counts, status and freshness (JSON).

## `summaryCsv` (type: `string`):

The per-source summary as a CSV file.

## `runStats` (type: `string`):

Totals, errors, timing and charging statistics for the run.

## `coverage` (type: `string`):

Agent mode only: jurisdictions queried with result counts and status (completed / no_match / failed), plus skipped jurisdictions and why.

# 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": [
        "chicago",
        "los_angeles",
        "new_york_city",
        "austin",
        "seattle"
    ],
    "lastNDays": 7,
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("exuberantly_inventiveness/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 = {
    "cities": [
        "chicago",
        "los_angeles",
        "new_york_city",
        "austin",
        "seattle",
    ],
    "lastNDays": 7,
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("exuberantly_inventiveness/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 '{
  "cities": [
    "chicago",
    "los_angeles",
    "new_york_city",
    "austin",
    "seattle"
  ],
  "lastNDays": 7,
  "maxItems": 100
}' |
apify call exuberantly_inventiveness/us-building-permits --silent --output-dataset

```

## MCP server setup

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