# New York Building Permits Scraper | Chicago, LA, 12 Cities (`aurelix/building-permits-scraper`) Actor

Scrape building permits from 12 US cities in one run at $1.50 per 1,000 permits, cheaper than the leading tools, with a new-or-changed mode and contractor-only filter. NYC, LA, Chicago, Austin and more in one schema: type, address, valuation, status, contractor, phone.

- **URL**: https://apify.com/aurelix/building-permits-scraper.md
- **Developed by:** [Aurelix](https://apify.com/aurelix) (community)
- **Categories:** Real estate, Lead generation, Business
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.05 / 1,000 permit results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

### What is New York Building Permits Scraper?

**Get new building permits from 12 US cities in one run (type, address, valuation, status, contractor) for $1.50 per 1,000 permits, no login.**

For contractors, suppliers and construction sales teams. NYC, LA, Chicago, Austin and more in one 30-field schema, with a new-or-changed mode and a contractor-only filter. Your first run with the example input costs about $0.051 (30 permits in our test run).

[![New York Building Permits Scraper: example output from a real run](https://api.apify.com/v2/key-value-stores/twkCCtTWzsi8fVbx5/records/building-permits-scraper-card-v2.png)](https://console.apify.com/actors/Us8xgEzGbslTLwsMd?addFromActorId=Us8xgEzGbslTLwsMd)

| | |
|---|---|
| **Cities** | Seattle, Chicago, New York City, Los Angeles, San Francisco, Austin, Baton Rouge, Cincinnati, Mesa, New Orleans, Norfolk and Orlando |
| **Filters** | Days back (up to 90), permit type, status, keywords, minimum valuation, contractor-only |
| **Output** | 30 fields per permit; JSON, CSV, Excel, API |
| **Automate** | Schedules, webhooks, Zapier, Make, n8n, Google Sheets, MCP for AI agents |
| **Price** | $1.50 per 1,000 permits ($1.05 per 1,000 permits on paid Apify plans) |
| **Login needed** | No |

### Daily monitor: only what's new, every morning

Set it once, get only the new permits every morning. With **Only new or changed since last run** on, the first run returns everything that matches; each later run returns only permits that are new or whose status changed.

```json
{
  "cities": [
    "nyc",
    "chicago"
  ],
  "daysBack": 7,
  "permitTypes": [
    "new",
    "alter"
  ],
  "minValuation": 100000,
  "incremental": true,
  "stateKey": "nyc-chicago-daily"
}
```

1. Paste this input into the **Input** tab (JSON view) and click **Save as a new task**; it appears under **Saved tasks**.
2. Open the task from **Saved tasks** and click **Schedule**.
3. Choose **Daily**, pick the hour, and save.

**Cost example:** 2 cities, about 40 new or changed permits a day ≈ $1.98/month on the free plan ($1.44 on paid plans): one run a day for 30 days, start fee included. The first run returns everything that matches, so it costs more.

Add a Slack incoming-webhook URL in `slackWebhookUrl` (or any URL in `webhookUrl`) to get a short digest of each run's new permits; nothing is sent when a run finds nothing.

### Why New York Building Permits Scraper users pick this one

- **Twelve cities, one schema.** One 30-field format for a single spreadsheet or CRM.
- **25% under top alternatives.** $1.50 per 1,000 permits against $2.00.
- **Status changes, not just new.** New-or-changed mode returns permits whose status moved.
- **Contractors named.** Contractor company in nine cities; business phone in three.
- **Late cities named.** The run status names any city behind on publishing.

### Get started in 3 steps

1. Pick the cities and how many days back to look; the defaults return permits issued in the last 7 days in all twelve cities, up to the newest 1,000 per city (busy weeks in NYC, Los Angeles and Austin exceed that: the run status says which cities hit the cap, and 'Max results per city' raises it).
2. Optionally narrow it: permit types, statuses, keywords, minimum valuation, contractor-only; turn on 'Only new or changed since last run' for a daily feed.
3. Click Start, then download JSON, CSV or Excel, or schedule the run and send results to Google Sheets, a CRM, Zapier, Make or n8n.

**[▶ Try it with the example input](https://console.apify.com/actors/Us8xgEzGbslTLwsMd?addFromActorId=Us8xgEzGbslTLwsMd)**

The form opens with an example input already filled in: that run costs about $0.051 on the free plan.

### How much does it cost to scrape US building permits?

Pay per event: you pay only for what the run returns, plus a small start fee. Bronze, Silver, Gold and higher Apify plans pay less per result.

| Permits | Free plan | Paid plans (Bronze, Silver, Gold) |
|---|---|---|
| 100 | $0.16 | $0.11 |
| 1,000 | $1.51 | $1.06 |
| 10,000 | $15.01 | $10.51 |

Totals include the $0.006 start fee per run, rounded to the cent. Apify's free plan includes $5 of credit a month, enough for about 3,300 permits.

No charge for cities that return nothing; the run start fee covers querying the cities when your filters match nothing. No proxy is used.

#### Billing events

| Event | Free plan | Paid plans (Bronze, Silver, Gold) |
|---|---|---|
| `permit-result` | $1.50 per 1,000 permits | $1.05 per 1,000 permits |
| `apify-actor-start` | $0.006 per run | $0.006 per run |

### New York Building Permits Scraper vs alternatives

| | **This Actor** | pink_comic/building-permits-construction-leads | handstands.io/us-building-permit-scraper |
|---|---|---|---|
| **Price per 1,000 permits, free plan** | $1.50 | $2.00 | $10.00 |
| **Price per 1,000 permits, paid plans** | $1.05 | $2.00 | $10.00 |
| **Start fee per run** | $0.006 | $0.0001 | $0.0002 (at 4 GB) |
| **Platform usage billed on top** | No | No | No |
| **Cities in one run** | 12 | 1 (47+ sources, one per run) | 13 to 36 (page and input differ) |
| **Only new or changed permits since last run** | ✓ | ✗ | ✗ |
| **Contractor-only filter** | ✓ | ✗ | ✗ |
| **Keyword and minimum project value filters** | ✓ both | Keyword only | Value only |
| **Owner and applicant names** | ✓ 5 cities, as published | ✓ owner where published | not stated |
| **Contractor person, phone, email and address** | ✓ as published | contractor company | not stated |
| **Slack or webhook digest after each run** | ✓ | not stated | not stated |

Prices checked regularly on each Actor's Store page.

### Benchmarks: how we compare

| Test | Input | Result | Run time |
|---|---|---|---|
| First run (prefilled input) | Seattle, Chicago and Austin, 10 per city | 30 permits for $0.051 in total | not recorded |
| All 12 cities | 2 days back, 30 per city | 275 permits | 11 s |
| Incremental repeat | the same input again with the new-or-changed mode | 210 different permits, no permit returned twice | not recorded |
| Small daily check | all 12 cities, 3 days back, 10 per city | 100 permits; New York City and Los Angeles returned 0 because they had not yet published those days, and the status said so | 9 s |
| Nothing matches | all 12 cities, 90 days back, no per-city limit, a keyword that matches nothing | 0 permits, only the start fee charged | 112 s |
| Field accuracy | 10 records checked against the source rows of the city portals | 10 of 10 matched |  |
| Completeness | one week of permits in Seattle, Chicago, Los Angeles and San Francisco | 95 of 95, 459 of 459, 833 of 833 and 249 of 249 distinct permits |  |
| Person fields | all 12 cities, 7 days back, no cap (local run) | 6,931 permits; owner name on 98% of NYC, 96% of Chicago, 97% of New Orleans, 76% of Baton Rouge and 71% of Orlando permits; contractor person on 100% of NYC, 89% of Austin and 97% of Orlando; 0 names in Los Angeles |  |

Apify cloud runs at the default 256 MB with no proxy, one run per row; accuracy and completeness come from our release checks of the same code (completeness covered the first five cities). Run times depend mostly on how fast each city's portal answers.

### What data you get

**New York Building Permits Scraper** turns the official open-data permit records of 12 US cities (Seattle, Chicago, New York City (DOB NOW), Los Angeles, San Francisco, Austin, Baton Rouge, Cincinnati, Mesa, New Orleans, Norfolk and Orlando) into one 30-field schema: permit number, type and subtype, description of work, address, ZIP code, neighbourhood, declared valuation, status, applied, issued, expiry and completion dates, the contractor (company, person, phone, email and address), owner and applicant names and Chicago's full contact list where the city publishes them, and coordinates. Filter by days back, permit type, status, keywords, minimum valuation or contractor-only, and switch on the new-or-changed mode for a daily lead feed.

- Permit number, permit type and subtype (class, work type, filing reason or proposed use)
- Description of work, primary address and all addresses (San Francisco), ZIP code, neighbourhood, community area or council district
- Declared project value (USD) and current status
- Applied, issued, expiry and completion dates (YYYY-MM-DD) where the city publishes them
- Contractor company (9 of 12 cities), phone (Austin, Mesa, Orlando), email (Mesa), qualifying person (NYC, Austin, Orlando) and address (NYC, Austin, Baton Rouge, Mesa, Orlando)
- Property owner name (Chicago, NYC, Baton Rouge, New Orleans, Orlando), applicant name (Chicago, NYC, Baton Rouge, Mesa, New Orleans) and Chicago's full contact list (role, name, city, state, ZIP)
- Latitude and longitude, a link to the permit record, and a stable permit_key for joins and dedupe

| city | permit_number | permit_type | address | valuation | issued_date | contractor_company | contractor_phone | owner_name |
|---|---|---|---|---|---|---|---|---|
| Austin | 2026-142494 EP | Electrical Permit | 10 LAS BRISAS DR |  | 2026-11-03 | American Electric | (512) 579-6216 |  |
| Orlando | BLD2026-13013 | Building Permit | 2802 SUGARHILL CT | 35910 | 2026-11-04 | US ALUMINUM SERVICES CORP | (407) 968-7195 | VAZQUEZ KAYLA R, VAZQUEZ VALENTIN A |
| New Orleans | 26-31948-ROOF | Residential Re-Roofing | 4725 Tchoupitoulas St | 21642 | 2026-11-03 | Garcia Roofing Replacement, LLC |  | Amanda Frank |
| Chicago | 101044829 | SIGNS | 33 W ILLINOIS ST | 6750 | 2026-11-03 | DOYLE SIGNS INC |  | FIRST FM JOINT VENTRUE |
| Mesa | PMT25-23377 | Tenant Improvement (Interior Only) | 4140 S SIGNAL BUTTE RD | 6236359.98 | 2026-11-02 | GRIDLINE CONSTRUCTION INC |  |  |
| San Francisco | 202610209691 | otc alterations permit | 1758 44th Av | 2500 | 2026-11-03 |  |  |  |

One full permit record, exactly as a real run returned it (long text and lists shortened here). From a real run:

```json
{
  "permit_key": "austin:2026-142494 EP",
  "city": "Austin",
  "state": "TX",
  "permit_number": "2026-142494 EP",
  "permit_type": "Electrical Permit",
  "permit_subtype": "Residential (Homebuilder Loop)",
  "description": "Building a temporary service for construction of a single family dwelling in an ETJ",
  "address": "10 LAS BRISAS DR",
  "addresses": [
    "10 LAS BRISAS DR"
  ],
  "zip_code": "78746",
  "neighborhood": null,
  "valuation": null,
  "status": "Active",
  "applied_date": "2026-10-28",
  "issued_date": "2026-11-03",
  "expires_date": "2027-05-02",
  "completed_date": null,
  "contractor_company": "American Electric",
  "contractor_phone": "(512) 579-6216",
  "contractor_name": "James Hallam",
  "contractor_address": "PO BOX 449 SPICEWOOD 78669",
  "owner_name": null,
  "applicant_name": null,
  "contacts": [],
  "latitude": null,
  "longitude": null,
  "url": "https://abc.austintexas.gov/web/permit/public-search-other?t_detail=1&t_selected_folderrsn=13797122",
  "source_url": "https://abc.austintexas.gov/web/permit/public-search-other?t_detail=1&t_selected_folderrsn=13797122",
  "scraped_at": "2026-11-07T16:33:08Z"
}
```

### Use cases

- Contractors and subcontractors finding new projects to bid on, e.g. solar, roofing or ADUs
- Building-material and equipment suppliers targeting contractor companies with fresh permits
- Construction and real-estate analysts tracking project value and activity by neighbourhood
- Lead-generation services sending clients a daily list of new high-value permits

### Use-case recipes

#### Daily contractor lead feed

For suppliers and subcontractors selling to builders. Pick your cities, keep only permits that name a contractor company and set a minimum value. Turn on the new-or-changed mode and schedule it daily; send `contractor_company`, `address`, `valuation` and `description` to your CRM, and use Google Maps Businesses to find each company's website and phone.

```json
{
  "cities": [
    "austin",
    "chicago",
    "mesa"
  ],
  "daysBack": 7,
  "contractorOnly": true,
  "minValuation": 100000,
  "maxResultsPerCity": 50,
  "incremental": true,
  "stateKey": "contractor-leads"
}
```

#### Solar and roofing permits for installers

For solar, roofing and HVAC companies tracking where work is happening. Filter by keywords in the description of work. Group the rows by `zip_code` or `neighborhood` to see which areas are busiest, and map them with `latitude` and `longitude`.

```json
{
  "cities": [
    "seattle",
    "san-francisco",
    "austin"
  ],
  "daysBack": 14,
  "keywords": [
    "solar",
    "roof"
  ],
  "maxResultsPerCity": 100
}
```

#### Track large new construction projects

For market researchers and real-estate analysts. Keep new-building permits above a high value across several cities. Sort by `valuation`, and watch `status` and `completed_date` on later runs to follow each project.

```json
{
  "cities": [
    "nyc",
    "chicago",
    "los-angeles"
  ],
  "daysBack": 30,
  "permitTypes": [
    "new"
  ],
  "minValuation": 1000000,
  "maxResultsPerCity": 100
}
```

#### Weekly digest in Slack

For sales teams that want a heads-up, not a spreadsheet. Schedule the task weekly with the new-or-changed mode and paste a Slack webhook URL; each run posts the count of new permits and the top 10 with links. Use 10 or more days back if you include Los Angeles, which publishes weekly.

```json
{
  "cities": [
    "orlando",
    "new-orleans",
    "baton-rouge"
  ],
  "daysBack": 10,
  "maxResultsPerCity": 50,
  "incremental": true,
  "slackWebhookUrl": "https://hooks.slack.com/services/T000/B000/XXXX"
}
```

### Input

| Field | Type | What it does | Default |
|---|---|---|---|
| `cities` (Cities) | array | Which city datasets to read, all building permits issued by the city: 'seattle', 'chicago', 'nyc' (DOB NOW approved work permits)... | \["seattle", "chicago", "nyc", "los-angeles", "san-francis... |
| `maxResultsPerCity` (Max results per city) | integer | Upper limit of results per city after filters, newest first. 0 = no limit (at most 50,000 rows are read... | 1000 |
| `daysBack` (Issued in the last N days) | integer | Keep permits issued on or after today minus this many days (UTC). | 7 |
| `permitTypes` (Permit types) | array | Keep permits whose type or subtype contains one of these (case-insensitive), e.g. \['new', 'demolition', 'plumbing', 'alter', 'single family']. |  |
| `statuses` (Statuses) | array | Keep permits whose status contains one of these (case-insensitive), e.g. \['issued', 'active', 'complete']. |  |
| `keywords` (Keywords) | array | Keep permits whose description of work or address contains one of these (case-insensitive), e.g. \['solar', 'roof', 'ADU', 'Broadway']. |  |

All 12 fields, with examples: see the **Input** tab.

### Switching from pink_comic/building-permits-construction-leads

Already running `pink_comic/building-permits-construction-leads`? Map its input fields to this Actor's like this:

| `pink_comic/building-permits-construction-leads` input | This Actor's input | Notes |
|---|---|---|
| `city` | `cities` | A list: up to 12 cities in one run and one schema (seattle, chicago, nyc, los-angeles, san-francisco, austin, baton-rouge, cincinnati, mesa, new-orleans, norfolk, orlando). Other cities are not covered. |
| `keyword` | `keywords` | A list, matched case-insensitively in the description of work and the address. Contractor names are not searched; use `contractorOnly` to keep permits that name one. |
| `permitType` | `permitTypes` | A list of partial matches on the permit type or subtype, e.g. `new`, `alter`, `demolition`. |
| `dateFrom` / `dateTo` | `daysBack` | A rolling window: permits issued on or after today minus this many days (0 to 90). Fixed past date ranges are not supported. |
| `maxResults` | `maxResultsPerCity` | Applies per city after filters, newest first (default 1,000; 0 = no limit, up to 50,000 rows read per city). |
| no equivalent | `minValuation` | New: keep permits with a declared project value of at least this many US dollars. |
| no equivalent | `statuses` | New: partial matches on the permit status, e.g. `issued`, `complete`. |
| no equivalent | `incremental` + `stateKey` | New: return only permits not returned before, plus permits whose status changed, for a daily or weekly schedule. |

- One run covers all your cities, so a 5-city feed is one scheduled task instead of five.
- Every record has the same 30 fields whatever the city; empty fields mean the city does not publish that value (see the FAQ on contractors).
- Price per permit is lower ($1.50 against $2.00 per 1,000), but the start fee is higher ($0.006 per run), which a run of 4 or more permits recovers.
- Owner, applicant and contractor names are returned as each city publishes them (none in Los Angeles).

### Use with AI agents (Apify MCP server, Claude, ChatGPT, n8n AI agent)

New York Building Permits Scraper is a ready-made tool for AI agents. Through the Apify MCP server an agent reads this Actor's input schema, fills in the input from your request, starts the run and reads the permits back. You pay the same per-result price as a run started by hand, from your own Apify account.

#### Example prompts

- "List new construction permits issued in Austin and Chicago in the last 7 days worth at least 100,000 dollars, with the contractor company and address"
- "Find solar and roof permits issued in Seattle, San Francisco and Orlando this week and give me a table of address, value and status"
- "Which contractor companies pulled the most building permits in New York City in the last 14 days? Count them for me"

#### Claude (claude.ai and Claude Desktop)

Open **Settings > Connectors**, choose **Add custom connector**, paste `https://mcp.apify.com/?tools=aurelix/building-permits-scraper` and sign in to Apify when asked. Then ask Claude one of the prompts above.

#### Claude Code, Cursor, VS Code and other MCP clients

```bash
claude mcp add --transport http apify "https://mcp.apify.com/?tools=aurelix/building-permits-scraper"
```

Clients configured with JSON take the same URL:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com/?tools=aurelix/building-permits-scraper"
    }
  }
}
```

A client without Apify sign-in sends the header `Authorization: Bearer <YOUR_APIFY_TOKEN>`; to run the server locally instead, use `npx -y @apify/actors-mcp-server --actors aurelix/building-permits-scraper` with `APIFY_TOKEN` set.

#### ChatGPT

Where your ChatGPT plan offers custom connectors (developer mode), add `https://mcp.apify.com/?tools=aurelix/building-permits-scraper` as a connector, sign in to Apify, and ask for the data in plain words.

#### n8n AI agent

Give an **AI Agent** node an **MCP Client Tool** with the endpoint `https://mcp.apify.com/?tools=aurelix/building-permits-scraper` and a Bearer credential holding your Apify token. The agent can then call New York Building Permits Scraper whenever a workflow step needs permits; for a fixed, non-agent workflow use Apify's n8n node with **Run Actor** instead.

### Use it from AI agents (MCP), the API or no-code

#### Copy this to your AI assistant

```text
Use the Apify Actor aurelix/building-permits-scraper (New York Building Permits Scraper) through Apify's MCP server or API. Main input: cities (Cities); maxResultsPerCity (Max results per city). Example input: {"cities": ["nyc", "chicago"], "daysBack": 1, "permitTypes": ["new", "alter"], "minValuation": 100000, "contractorOnly": true, "incremental": true}. Each result is one permit with fields such as permit_key, city, state, permit_number, permit_type, permit_subtype, description, address. It costs $1.50 per 1,000 permits on Apify's free plan plus a $0.006 start fee per run, and needs no login.
```

MCP server URL for this Actor: `https://mcp.apify.com/?tools=aurelix/building-permits-scraper` (setup for each client in the section above).

#### API

Start a run and read the dataset with Apify's REST API or the Python and JavaScript clients:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("aurelix/building-permits-scraper").call(run_input={'cities': ['nyc', 'chicago'], 'daysBack': 1, 'permitTypes': ['new', 'alter'], 'minValuation': 100000, 'contractorOnly': True, 'incremental': True})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

#### No-code: schedule it in 3 clicks

Send the results to Google Sheets, Zapier, Make, n8n, Slack or any webhook URL.

1. Fill in the input, then click **Save as a new task**.
2. In the task, click **Schedule** and pick daily or weekly (Apify Schedules).
3. Turn on **Only new or changed since last run** so each run returns only what is new, and paste a Slack or webhook URL into **Slack webhook URL** / **Webhook URL** to get a digest of the new items (count plus the top 10) after every run.

Prefer n8n or Make? Ask in the **Issues** tab and we will share a ready-made workflow for it.

### FAQ

#### Can I scrape US building permits without login?

Yes. It never logs in, so you need no city portal account, password or cookies; only a free Apify account to run it.

#### Is there a US building permits API?

You can use this Actor as one. Start it with Apify's REST API or the Python and JavaScript clients and read the results as JSON (see the code above), or call it from an AI agent through MCP.

#### How much does it cost to scrape US building permits?

About $1.51 for 1,000 permits on Apify's free plan and $1.06 on paid plans, start fee included. The free $5 monthly credit covers about 3,300 permits.

#### Can I export US building permits data to Excel or Google Sheets?

Yes. Download the results as Excel, CSV, JSON, XML or HTML from the run's **Storage** tab, or send them to Google Sheets with Apify's Google Sheets integration or the API.

#### Is it legal to scrape US building permits?

It reads only public data any logged-out visitor can see: the official open-data APIs of the twelve cities. It goes at a polite pace, never logs in and never solves CAPTCHAs. It returns permit fields (type, address, work description, valuation, status, dates) and the owner, applicant and contractor fields as each city publishes them; Los Angeles records carry no names because its portal terms bar collecting personal information. Data is returned as shown publicly on the source; people can ask for removal by opening an issue on this Actor's Issues tab; if a city formally asks us to stop, this Actor will stop. You are responsible for using the data lawfully, incl. anti-spam and privacy laws; this is not legal advice.

#### Where does the data come from?

From each city's official open-data portal (all Socrata): Seattle Building Permits (data.seattle.gov, public domain), Chicago Building Permits (data.cityofchicago.org), NYC DOB NOW: Build Approved Permits (data.cityofnewyork.us), Los Angeles Building Permits Issued from 2020 to Present (data.lacity.org), San Francisco Building Permits (data.sf.gov, ODC PDDL), Austin Issued Construction Permits (data.austintexas.gov, public domain), East Baton Rouge Building Permits (data.brla.gov, public domain), Cincinnati Building Permits (data.cincinnati-oh.gov, public domain), Mesa Building Permits (citydata.mesaaz.gov), New Orleans Permits (data.nola.gov, CC0), Norfolk Permits (data.norfolk.gov) and Orlando Permit Applications (data.cityoforlando.net). Every record links back to its source.

#### Does it include owner and applicant names?

Yes, where the city publishes them: the property owner in Chicago, NYC, Baton Rouge, New Orleans and Orlando, the applicant in Chicago, NYC (filing representative), Baton Rouge, Mesa and New Orleans, and Chicago's full permit contact list (owner, applicant, contractors, architect, expediter, with city, state and ZIP). Los Angeles is left name-free because its open-data terms bar collecting personal information. Nothing is guessed; a field the city does not publish stays empty.

#### How fresh is it?

Each city publishes on its own schedule. In our checks the newest issue dates were 0 to 2 days old for Orlando, Chicago, San Francisco, Austin, Baton Rouge, Mesa, New Orleans, Norfolk, Seattle and Cincinnati, about 2 to 5 days for New York City (its 'daily' dataset is refreshed every few days) and up to about 10 days for Los Angeles (refreshed weekly). A run asking for fewer days than a city's lag returns 0 permits for that city; the run status then names the city and its newest published date. Use 7 or more days back with the new-or-changed mode for a daily feed (10 or more if you rely on Los Angeles), so nothing falls between refreshes.

#### Why is the contractor empty for some permits?

Los Angeles, San Francisco and Norfolk do not publish contractors in these datasets (Los Angeles names are left out under its portal terms), and Seattle publishes one on only a small share of permits. Contractors are returned as published, so some are licensed individuals (common in New Orleans). Only Austin, Mesa and Orlando publish a contractor phone.

#### How does 'new or changed since last run' work?

The Actor remembers each permit and its status for the same cities and filters (or for the state name you set). A permit comes back when it is new or when its status changes. Memory lasts 400 days.

#### What am I charged when nothing matches?

Only the $0.006 start fee. Permits are charged one by one as they are returned, so a city with no matches costs nothing. If every city fails to answer, the run ends as failed and no permit is charged.

#### Why did a city return 0 permits?

Usually because the city has not yet published the days you asked for: New York City runs about 2 to 5 days behind and Los Angeles up to about 10. The run status then names the city and its newest published date. Otherwise your filters matched nothing in that city.

#### What happens if one city's portal is down?

Each request is tried up to 4 times with growing waits. A city that still fails is named in the run status as failed and the other cities are returned as normal. If a city fails part-way through, the permits already read are kept and the status says so.

#### How does the per-city cap work?

Max results per city counts permits after your filters, newest issue date first, 1,000 by default. The run status names every city that hit the cap. Set it to 0 for no limit; at most 50,000 rows are read per city in one run.

#### What is permit_key?

A stable ID made of the city and the permit number (or the record key the city uses), the same in every run. Use it to join or de-duplicate permits across runs and cities. A permit listed on several rows by the city is returned once.

#### Does the new-or-changed memory depend on my filters?

Yes. The memory is keyed on the cities and filters (permit types, statuses, keywords, minimum value, contractor-only), not on days back. Changing any of them starts a new feed. Set State key to keep a feed while you edit its filters, or to run separate feeds side by side.

#### Which cities can I add?

Only the twelve listed. Each city needs its own field mapping and privacy review, so other cities are added on request: open an issue on the Issues tab naming the city.

### Lawful use

- B2B use only: records name owners, applicants and contractors as each city publishes them. Use the data only for business purposes such as trade leads or market research. Data is returned as shown publicly on the source; people can ask for removal by opening an issue on this Actor's Issues tab.
- No spam: contact people only with relevant, individual business messages, identify yourself, and honour every opt-out at once. Bulk unsolicited email built from this data is not allowed.
- You are responsible for complying with the anti-spam and privacy laws that apply to you and to the people you contact, including Canada's CASL, the US CAN-SPAM Act and the EU/UK GDPR (lawful basis, transparency, the right to object).
- Removal requests: open an issue on this Actor's Issues tab naming the person, email address or domain to remove. It is added to our suppression list and honoured within 7 days; from then on matching records are not returned.
- Owner, applicant and contractor fields are returned as each city publishes them; Los Angeles stays name-free under its portal terms. Data is returned as shown publicly on the source; people can ask for removal by opening an issue on this Actor's Issues tab.

### Limits (stated honestly)

- Twelve cities: Seattle, Chicago, New York City, Los Angeles, San Francisco, Austin, Baton Rouge, Cincinnati, Mesa, New Orleans, Norfolk and Orlando. Open an issue to ask for another city.
- New York City is DOB NOW work permits only (not legacy BIS permits); one record per work permit, sequence and work type (a permit re-issued under the same sequence appears once, at its newest issue date), and the dataset has no application date. Baton Rouge and Mesa list a few permits on several rows; these become one record with all addresses kept. Los Angeles is the building-permit dataset only (not separate electrical or mechanical permits).
- Publishing lag (as measured in our checks): New York City runs about 2 to 5 days behind and Los Angeles, which refreshes weekly, up to about 10 days; the other ten cities were 0 to 2 days behind. A look-back shorter than the lag returns 0 permits for that city, and the run status says so.
- Orlando is the permit-applications dataset filtered to issued permits; it has no description of work, and some records carry no address. Cincinnati, Norfolk and Orlando publish no description of work, so the permit type and subtype describe it. Baton Rouge covers East Baton Rouge Parish and all its permits are issued.
- Filtering is by issue date; permits applied for but not yet issued are not included.
- Valuation is the value declared by the applicant; Chicago express permits often carry none.
- Descriptions are returned as published, except in Los Angeles, whose portal terms bar collecting personal information: there personal names and contact sentences are removed, which occasionally masks a harmless word, such as a street or company named after a person, as '\[name removed]'.
- Default cap: 1,000 permits per city per run, newest first. The run status names any city that hit it; raise 'Max results per city' (0 = no limit) to get everything.
- Look-back is capped at 90 days and 50,000 rows per city per run; rows dated more than a day in the future (data-entry errors) are skipped.
- Chicago data notice: This site provides applications using data that has been modified for use from its original source, www.cityofchicago.org, the official website of the City of Chicago. The City of Chicago makes no claims as to the content, accuracy, timeliness, or completeness of any of the data provided at this site. The data provided at this site is subject to change at any time. It is understood that the data provided at this site is being used at one's own risk.

### Works great with

- **Then: [Google Maps Phone Scraper](https://apify.com/aurelix/google-maps-scraper)**: search the `contractor_company` names there to get each contractor's website and phone, then pass the websites to Company Contact Finder

### Related Aurelix tools

Public Aurelix Actors, grouped by the data they collect. All are pay-per-result and need no login.

#### Canada and government data

- **[Canada Building Permits](https://apify.com/aurelix/canada-building-permits-scraper)**: Building permits and development applications from 7 Canadian cities: address, type, status, dates, value, applicant, contractor and Toronto planner contact.

#### Jobs and hiring data

- **[Greenhouse Jobs Scraper](https://apify.com/aurelix/greenhouse-jobs-scraper)**: Live jobs from a company's Greenhouse, Lever, Ashby or SmartRecruiters board, with salary and Canadian province tags.
- **[LinkedIn Jobs Country Filter Scraper](https://apify.com/aurelix/linkedin-jobs)**: Public LinkedIn job postings by keyword and country: title, company, location, seniority, job type, salary text, description.
- **[Multiple Job Boards Scraper](https://apify.com/aurelix/multi-job-board-scraper)**: LinkedIn, about 50 company career sites, Remote OK and We Work Remotely jobs in one deduplicated list.

#### E-commerce and product data

- **[AliExpress Scraper API](https://apify.com/aurelix/aliexpress-product-search)**: AliExpress search results by keyword: price, discount, rating, units sold, ship-from country and sponsored flag.
- **[Amazon New Releases & Best Sellers](https://apify.com/aurelix/amazon-best-sellers)**: Amazon Best Sellers and New Releases top 100 on 10 marketplaces: rank, ASIN, price, rating, rank change.
- **[Shopify Product Export Scraper](https://apify.com/aurelix/shopify-products-scraper)**: Every public product of any Shopify store with variants, SKUs, prices, barcodes, stock counts and collections.

#### Leads and company data

- **[Newly Funded Companies Hiring](https://apify.com/aurelix/funded-companies-hiring)**: Companies that just raised money (SEC Form D), with their open roles and business contacts, as a new-only monitor.
- **[Google Maps Phone Scraper](https://apify.com/aurelix/google-maps-scraper)**: Local business lists from Google Maps: phones, websites, ratings, hours, coordinates; optional website emails and socials.
- **[Recently Funded Companies API](https://apify.com/aurelix/recently-funded-companies)**: US companies that just filed an SEC Form D: amount raised, industry, state, executives, confirmed website.
- **[Tech Stack API](https://apify.com/aurelix/tech-stack-detector)**: CMS, e-commerce platform, analytics, ad pixels, chat, CDN and email provider for each domain you enter.

#### Ad intelligence

- **[Competitor Watch](https://apify.com/aurelix/competitor-watch)**: One report per competitor with only what is new: Meta and TikTok ads, page changes, Shopify products and prices, jobs.
- **[Facebook Ad Library Search & API](https://apify.com/aurelix/facebook-ad-library-scraper)**: Facebook and Instagram business ads from the Meta Ad Library: copy, creatives, landing pages, dates, optional EU reach.

#### AI, content and SEO

- **[Google Trends by Region](https://apify.com/aurelix/google-trends-scraper)**: Google Trends interest over time, by region and rising queries for any number of keywords, plus trending searches.
- **[Google Autocomplete API](https://apify.com/aurelix/google-autocomplete-scraper)**: Expands seed keywords into hundreds of real Google and YouTube autocomplete phrases, tagged by search intent.
- **[PDF to Markdown OCR & Table Extraction](https://apify.com/aurelix/pdf-to-markdown)**: Turns linked PDF and Word files into Markdown per page, with tables as JSON rows, RAG chunks and OCR.
- **[Broken Link Crawler & SEO Audit](https://apify.com/aurelix/seo-audit-crawler)**: Audits a whole site: one row per page with SEO checks and broken links, plus a ranked issues summary.
- **[Website to Markdown API](https://apify.com/aurelix/website-to-markdown)**: Crawls a site and returns one row of clean main-content Markdown per page, with title, headings and links.

#### More data tools

- **[Tennis Betting Odds Scraper](https://apify.com/aurelix/tennis-odds-scraper)**: Tennis results and upcoming matches with opening and closing odds per bookmaker and implied probabilities.

### Recent changes

- **0.4**: New fields: owner_name, applicant_name, contractor_name, contractor_email, contractor_address and Chicago's contacts list; contractors are returned as published (individuals included) with their phone, and descriptions are kept whole outside Los Angeles, whose portal terms keep it name-free.
- **0.3**: When a city returns nothing because it has not yet published the requested days (New York City and Los Angeles lag by days), the run status names the city and its newest published date.
- **0.2**: Look-back capped at 90 days.

The full history is on the **Changelog** tab.

### Tested daily

An automated health check runs this Actor every day on a fixed input and checks that at least 12 permits come back with `permit_key`, `city`, `permit_number`, `issued_date`, `address`, `url` filled in; a failed check alerts the maintainer straight away.

### Your feedback

Missing a field, found a bug or need another filter? Open an issue on the **Issues** tab; we aim to answer within a day. If this Actor saved you time, a short review helps other people find it.

# Changelog

This Actor's version history is a separate document: https://apify.com/aurelix/building-permits-scraper/changelog.md

# Actor input Schema

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

Which city datasets to read, all building permits issued by the city: 'seattle', 'chicago', 'nyc' (DOB NOW approved work permits), 'los-angeles' (issued since 2020), 'san-francisco', 'austin' (issued construction permits), 'baton-rouge' (East Baton Rouge Parish), 'cincinnati', 'mesa', 'new-orleans', 'norfolk', 'orlando'. Example: \['nyc', 'austin'].

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

Keep permits issued on or after today minus this many days (UTC). Example: 1 for a daily feed, 7 for a weekly one. At most 90.

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

Keep permits whose type or subtype contains one of these (case-insensitive), e.g. \['new', 'demolition', 'plumbing', 'alter', 'single family']. Empty = all.

## `statuses` (type: `array`):

Keep permits whose status contains one of these (case-insensitive), e.g. \['issued', 'active', 'complete']. Empty = all.

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

Keep permits whose description of work or address contains one of these (case-insensitive), e.g. \['solar', 'roof', 'ADU', 'Broadway']. Empty = all.

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

Keep permits whose declared project value is at least this many US dollars. Permits with no value are dropped when this is above 0. Example: 100000.

## `contractorOnly` (type: `boolean`):

Keep only permits that name a contractor company (Seattle, Chicago, NYC, Austin, Baton Rouge, Cincinnati, Mesa, New Orleans and Orlando publish one; Los Angeles, San Francisco and Norfolk do not).

## `maxResultsPerCity` (type: `integer`):

Upper limit of results per city after filters, newest first. 0 = no limit (at most 50,000 rows are read per city).

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

Return only permits not returned by a previous run with the same cities and filters, plus permits whose status has changed. Use with a daily or weekly schedule.

## `stateKey` (type: `string`):

Name for the 'new since last run' memory. Leave empty to derive it from the cities and filters; set it to keep separate feeds apart, e.g. 'nyc-solar'.

## `slackWebhookUrl` (type: `string`):

After each run, post a short digest to Slack: how many results were saved (new ones only when 'Only new or changed since last run' is on) and the top 10 with links, e.g. https://hooks.slack.com/services/T000/B000/XXXX. Nothing is posted when the run saved nothing. Leave empty to skip.

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

After each run, POST the same digest as JSON (actor, newOnly, count, items = top 10 results, runUrl, text) to any URL, e.g. a Zapier, Make or n8n webhook. Nothing is sent when the run saved nothing. Leave empty to skip.

## Actor input object example

```json
{
  "cities": [
    "seattle",
    "chicago",
    "austin"
  ],
  "daysBack": 7,
  "permitTypes": [],
  "statuses": [],
  "keywords": [],
  "minValuation": 0,
  "contractorOnly": false,
  "maxResultsPerCity": 10,
  "incremental": false
}
```

# Actor output Schema

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

All building permits found in this 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": [
        "seattle",
        "chicago",
        "austin"
    ],
    "maxResultsPerCity": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("aurelix/building-permits-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "cities": [
        "seattle",
        "chicago",
        "austin",
    ],
    "maxResultsPerCity": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("aurelix/building-permits-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "cities": [
    "seattle",
    "chicago",
    "austin"
  ],
  "maxResultsPerCity": 10
}' |
apify call aurelix/building-permits-scraper --silent --output-dataset

```

## MCP server setup

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

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/Us8xgEzGbslTLwsMd/builds/OcZvF0UYmF3Ljyeud/openapi.json
