# NYC Building Permits & Construction Leads Scraper (`logiover/nyc-dob-now-building-permits-scraper`) Actor

Export NYC DOB NOW approved building permits with project cost, work type, contractor, owner, address and geolocation. Filter nearly one million records for construction leads and market intelligence. No API key.

- **URL**: https://apify.com/logiover/nyc-dob-now-building-permits-scraper.md
- **Developed by:** [Logiover](https://apify.com/logiover) (community)
- **Categories:** Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 results

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

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## NYC Building Permits & Construction Leads Scraper

Export current NYC DOB NOW approved building permits as clean, analysis-ready records. Each result combines the project address, issue date, work type, estimated job cost, applicant or contractor identity, license, owner details, job description and coordinates. The Actor uses the City of New York's public data service, needs no external API key and can produce hundreds of thousands of construction-market records.

### What can you do with this Actor?

- Build fresh construction lead lists by borough, work type, issue date and project value.
- Find contractors, permit applicants, filing representatives and property owners already involved in active work.
- Monitor renovation, plumbing, electrical, HVAC, structural and general-construction demand.
- Enrich real-estate, insurance, lending, building-material and local-market datasets.
- Export repeatable permit snapshots to Google Sheets, a database, BI tooling or your own API.

This is a bulk data Actor rather than a browser automation workflow. It reads the official `DOB NOW: Build – Approved Permits` dataset directly, so runs are fast, deterministic and not affected by website layout changes.

### Input

All filters are optional. An empty input exports the newest permits first.

| Field | Type | Description |
| --- | --- | --- |
| `boroughs` | string\[] | Exact borough names such as `MANHATTAN`, `BROOKLYN` or `QUEENS`. |
| `workTypes` | string\[] | Exact DOB work-type names, for example `Plumbing`, `Electrical`, `General Construction` or `Mechanical Systems`. |
| `permitStatuses` | string\[] | Exact permit statuses to include. |
| `issuedSince` | date | Earliest permit issue date, inclusive. |
| `issuedBefore` | date | Latest boundary date, exclusive. |
| `zipCodes` | string\[] | Project ZIP codes. |
| `applicantBusinessContains` | string | Case-insensitive applicant or contractor company search. |
| `ownerBusinessContains` | string | Case-insensitive property-owner company search. |
| `minEstimatedJobCost` | number | Minimum estimated project cost in USD. |
| `maxResults` | integer | Maximum unique permits to save, up to 500,000. |

Example for recent higher-value Brooklyn work:

```json
{
  "boroughs": ["BROOKLYN"],
  "issuedSince": "2026-01-01",
  "minEstimatedJobCost": 100000,
  "maxResults": 10000
}
```

### Output

One dataset item represents one approved work-permit record. Important fields include:

| Field | Meaning |
| --- | --- |
| `permitRecordId`, `workPermitNumber`, `jobFilingNumber` | Stable DOB identifiers for matching and deduplication. |
| `issuedDate`, `approvedDate`, `expiredDate`, `permitStatus` | Permit lifecycle. |
| `borough`, `address`, `zipCode`, `latitude`, `longitude` | Project location. |
| `workType`, `workOnFloor`, `jobDescription`, `estimatedJobCost` | Scope and value signals. |
| `applicantName`, `applicantBusinessName`, `applicantLicense` | Applicant or contractor lead fields. |
| `filingRepresentativeName`, `filingRepresentativeBusinessName` | Filing representative fields. |
| `ownerName`, `ownerBusinessName`, `ownerAddress` | Property-owner information available in the source. |
| `bin`, `block`, `lot`, `bbl` | NYC property identifiers. |
| `sourceUrl`, `scrapedAt` | Lineage and export timestamp. |

```json
{
  "workPermitNumber": "B01234567-I1-PL",
  "issuedDate": "2026-07-31",
  "borough": "BROOKLYN",
  "address": "125 EXAMPLE AVENUE",
  "workType": "Plumbing",
  "estimatedJobCost": 185000,
  "applicantBusinessName": "EXAMPLE CONTRACTING LLC",
  "ownerBusinessName": "EXAMPLE OWNER LLC",
  "latitude": 40.68,
  "longitude": -73.95
}
```

### Practical lead-generation patterns

For the freshest leads, set `issuedSince` to the beginning of the current month and sort downstream by `issuedDate`. Suppliers can segment by `workType`; lenders and insurers can combine project cost with address and owner fields; contractors can monitor filings outside their existing accounts. Large exports are paginated automatically, and each record is deduplicated by its DOB tracking identifier.

The source occasionally leaves individual columns blank because not every filing requires every field. The Actor preserves meaningful `null` values rather than inventing data.

### Integrations and API

Run the Actor from the Apify Console, Scheduler, REST API, JavaScript or Python client. Dataset results can be downloaded as JSON, JSONL, CSV, Excel, XML or RSS, or connected to webhooks, Google Sheets, Make, Zapier and other Apify integrations.

```bash
curl -X POST "https://api.apify.com/v2/acts/logiover~nyc-dob-now-building-permits-scraper/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"boroughs":["QUEENS"],"maxResults":5000}'
```

The Actor can also be exposed as a tool through Apify's MCP server, allowing an AI agent to request current permit leads with structured filters.

### FAQ

**Does it need a NYC Open Data token?** No. It works without an external API key.

**How much data can it return?** Up to 500,000 unique records per run, subject to the filters and records available in the official dataset.

**Is this historical or current data?** The source is the current DOB NOW approved-permits dataset and is updated by NYC.

**Are contractor phone numbers or emails included?** No. The source exposes business, person, address and license fields, not guaranteed phone or email data.

**Why is estimated cost sometimes null?** Some permit rows do not report a usable cost value.

**Can I run it every day?** Yes. Use an Apify schedule and an issue-date window, then deduplicate downstream by `permitRecordId`.

**Can I filter arbitrary text in job descriptions?** The current version focuses on stable lead filters. Export the records and apply free-text classification downstream when needed.

**Is the data legal to use?** The Actor accesses public NYC data. You remain responsible for your use, outreach rules and applicable privacy or marketing law.

### Responsible use

This Actor is not affiliated with or endorsed by the New York City Department of Buildings. Data is provided as reported by the public source and may be corrected or updated later. Verify critical decisions against official records and use personal information responsibly.

### Changelog

#### 2026-08-04

- Initial release using the current DOB NOW approved-permits dataset.
- Added bulk pagination, stable deduplication and no-key operation.
- Added borough, work type, date, ZIP, business-name and project-cost filters.
- Validated normalized identifiers, dates, lead fields, cost values and geolocation output.

# Actor input Schema

## `boroughs` (type: `array`):

Only return permits in selected NYC boroughs. Leave empty for all boroughs.

## `workTypes` (type: `array`):

Exact DOB work type names, for example General Construction, Plumbing, Electrical, or Construction Fence.

## `permitStatuses` (type: `array`):

Exact permit statuses, such as Issued or Signed-off.

## `issuedSince` (type: `string`):

Only permits issued on or after this date.

## `issuedBefore` (type: `string`):

Only permits issued before this date.

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

Exact five-digit NYC ZIP codes.

## `applicantBusinessContains` (type: `string`):

Case-insensitive contractor or applicant business-name filter.

## `ownerBusinessContains` (type: `string`):

Case-insensitive owner business-name filter.

## `minEstimatedJobCost` (type: `number`):

Client-side minimum estimated project value.

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

Maximum number of permit records saved to the dataset.

## Actor input object example

```json
{
  "boroughs": [],
  "workTypes": [],
  "permitStatuses": [],
  "zipCodes": [],
  "applicantBusinessContains": "",
  "ownerBusinessContains": "",
  "maxResults": 200
}
```

# Actor output Schema

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

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "maxResults": 200
};

// Run the Actor and wait for it to finish
const run = await client.actor("logiover/nyc-dob-now-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 = { "maxResults": 200 }

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

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

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

```

## CLI example

```bash
echo '{
  "maxResults": 200
}' |
apify call logiover/nyc-dob-now-building-permits-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=logiover/nyc-dob-now-building-permits-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/ZKbY6i48u39PcyckA/builds/KeLA9OcBygIhC6Tz8/openapi.json
