# NYC Business License Scraper (`crawlerbros/nyc-business-license-scraper`) Actor

Search New York City's official business license registry - find active and historical licensed businesses by name, category, borough, license status, or phone number. Sourced live from NYC Open Data (Department of Consumer and Worker Protection).

- **URL**: https://apify.com/crawlerbros/nyc-business-license-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Lead generation, Real estate, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 Business License Scraper

Search New York City's official business license registry. Find active and historical licensed businesses — home improvement contractors, hotels, tobacco retailers, locksmiths, car washes, pawnbrokers, and 40+ other licensed trades — by business name, category, borough, license status, license number, or phone number. Sourced live from the NYC Department of Consumer and Worker Protection (DCA) open dataset. No login, no API key, no cookies required.

### What this actor does

- **Four modes:** `search` (name + filters), `byLicenseNumbers` (exact license lookup), `byPhoneNumbers` (reverse phone lookup), `byBusinessUniqueIds` (all licenses held by one business entity)
- **Full filter surface:** business category (48 licensed trades), NYC borough, City Council district, Community Board, license status, license type, address type, ZIP code, license issue date range, license expiration date range
- **Sortable:** relevance, business name A-Z/Z-A, newest/oldest license, expiring soonest/latest
- **Geo-located** — latitude/longitude included whenever the source record has an address on file
- **Empty fields are omitted** — every record only contains fields NYC actually has on file

### Output per business

- `licenseNumber` — official NYC DCA license number
- `businessName`, `dbaName` (trade name, if different from legal name)
- `businessUniqueId`
- `category` — licensed business category (e.g. `Home Improvement Contractor`, `Hotel`, `Locksmith`)
- `licenseType` — `Individual` or `Premises`
- `licenseStatus` — e.g. `Active`, `Expired`, `Out of Business`
- `licenseCreationDate`, `licenseExpirationDate`
- `detail` — extra license conditions where published (e.g. product categories/stand counts for vending stands, vehicle/bicycle capacity for sightseeing buses)
- `phone` — normalized `(XXX) XXX-XXXX` format
- `addressStreet`, `addressStreet2`, `addressStreet3` (rare secondary/tertiary address lines, when NYC has one on file), `addressUnit` (suite/apt/floor, e.g. `STE 3012`), `addressCity`, `addressState`, `addressZip`, `borough`, `addressType` (e.g. `Complete Address`, `Cross Street (Intersection)`, `P.O. Box`, `Place (Landmark)`), `fullAddress`
- `communityBoard`, `councilDistrict`, `neighborhood` (NYC Neighborhood Tabulation Area code, e.g. `MN17`)
- `buildingIdNumber` (NYC DOB Building Identification Number / BIN), `taxBlockLot` (Borough-Block-Lot / BBL tax parcel ID)
- `censusTract`, `censusBlock` (2010 Census geography, where mapped)
- `latitude`, `longitude`
- `sourceUrl` — direct link to the live NYC Open Data record
- `recordType: "businessLicense"`, `scrapedAt`

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search` / `byLicenseNumbers` / `byPhoneNumbers` / `byBusinessUniqueIds` |
| `searchQuery` | string | `pizza` | Free-text match on business legal name or DBA trade name |
| `licenseNumbers` | array | – | Exact license numbers (mode=byLicenseNumbers) — either the older `-DCA` suffix or the newer `-DCWP` suffix |
| `phoneNumbers` | array | – | Phone numbers, any format (mode=byPhoneNumbers) |
| `businessUniqueIds` | array | – | Exact Business Unique IDs, e.g. `BA-1216876-2022` (mode=byBusinessUniqueIds) — returns every license held by that business entity |
| `category` | select | – | One of 48 licensed business categories |
| `borough` | select | – | `Manhattan` / `Brooklyn` / `Queens` / `Bronx` / `Staten Island` / `Outside NYC` |
| `licenseStatus` | select | – | `Active`, `Expired`, `Out of Business`, etc. |
| `licenseType` | select | – | `Individual` or `Premises` |
| `zipCode` | string | – | 5-digit NYC ZIP code |
| `councilDistrict` | select | – | NYC City Council district (`01`-`51`) |
| `communityBoard` | select | – | NYC Community District Board code (e.g. `301` = Brooklyn CB 3) |
| `addressType` | select | – | How the address is recorded on file: `Complete Address`, `Cross Street (Intersection)`, `Place (Landmark)`, or `P.O. Box` |
| `createdAfter` / `createdBefore` | date | – | Restrict to licenses first issued on/after or on/before a given date (`YYYY-MM-DD`) |
| `expiresAfter` / `expiresBefore` | date | – | Restrict to licenses expiring on/after or on/before a given date (`YYYY-MM-DD`) — combine with `licenseStatus=Active` to find licenses expiring soon |
| `sortBy` | select | `relevance` | `relevance` / `nameAsc` / `nameDesc` / `newest` / `oldest` / `expiringSoon` / `expiringLatest` |
| `maxItems` | int | `20` | Hard cap on emitted records (1–5000) |

#### Example: active home improvement contractors in Brooklyn

```json
{
  "mode": "search",
  "category": "Home Improvement Contractor",
  "borough": "Brooklyn",
  "licenseStatus": "Active",
  "maxItems": 100
}
```

#### Example: lookup by exact license number

```json
{
  "mode": "byLicenseNumbers",
  "licenseNumbers": ["0002902-DCA", "0390712-DCA"]
}
```

#### Example: reverse phone lookup

```json
{
  "mode": "byPhoneNumbers",
  "phoneNumbers": ["(718) 237-1166"]
}
```

#### Example: all licenses held by one business

```json
{
  "mode": "byBusinessUniqueIds",
  "businessUniqueIds": ["BA-1216876-2022"]
}
```

#### Example: hotels with a license expiring in the next few months

```json
{
  "mode": "search",
  "category": "Hotel",
  "licenseStatus": "Active",
  "expiresBefore": "2026-12-31",
  "maxItems": 200
}
```

#### Example: active licenses expiring soonest (renewal outreach)

```json
{
  "mode": "search",
  "licenseStatus": "Active",
  "sortBy": "expiringSoon",
  "maxItems": 100
}
```

#### Example: active licensed businesses in a City Council district

```json
{
  "mode": "search",
  "councilDistrict": "03",
  "licenseStatus": "Active",
  "maxItems": 100
}
```

### Use cases

- **Due diligence** — verify a contractor, locksmith, or tow-truck company is actually licensed and active before hiring
- **Lead generation** — build category-specific prospect lists (e.g. all active hotels or car washes in a borough)
- **Consumer protection research** — check whether a business has an expired, suspended, or revoked license
- **Local market analysis** — count and map licensed businesses by category and borough
- **Reverse phone / name lookup** — identify the licensed business behind a phone number or license number
- **Multi-license entity lookup** — find every license (past and present, all categories) held by one business using its Business Unique ID
- **Renewal outreach** — find active licenses expiring in a given window using `expiresAfter`/`expiresBefore`
- **Civic / constituent services** — pull every licensed business in a specific City Council district using `councilDistrict`

### FAQ

**What's the data source?**  The NYC Department of Consumer and Worker Protection (DCA) "Legally Operating Businesses" open dataset, published on NYC Open Data (`data.cityofnewyork.us`), a public, no-auth Socrata API maintained by New York City government.

**Which businesses are covered?**  Any trade that requires a DCA license to operate in NYC — home improvement contractors, hotels, tobacco/e-cigarette retailers, electronics stores, locksmiths, pawnbrokers, tow truck companies/drivers, sightseeing guides, secondhand dealers, debt collectors, employment agencies, and more. Businesses that don't require a DCA license (e.g. most restaurants, which are licensed separately by the Health Department) are not in this dataset.

**How current is the data?**  NYC Open Data refreshes this dataset regularly (typically daily); the actor always queries live.

**Why do some records lack a phone, borough, or coordinates?**  Not every license type collects every field — for example, individual license holders (as opposed to business premises) may not have a mapped street address. The actor only includes fields NYC actually published for that specific license.

**Is there a cost or rate limit?**  The actor uses NYC's free public Socrata API — no proxy, no API key, and no per-request cost.

**Can I search partial business names?**  Yes — `searchQuery` matches anywhere in the legal business name or the DBA trade name, case-insensitive.

**What is a Business Unique ID and how is it different from a license number?**  A license number identifies one specific license (one category, one issue/expiration cycle). A Business Unique ID identifies the underlying business entity and stays the same across every license that entity holds — a business can be licensed for multiple categories (e.g. a hotel that's also a garage) or renew under a new license number over time, all under the same Business Unique ID. Use `mode=byBusinessUniqueIds` to pull every license on file for one business.

**Why do some license numbers end in `-DCA` and others in `-DCWP`?**  The licensing agency was renamed from the Department of Consumer Affairs (DCA) to the Department of Consumer and Worker Protection (DCWP) in 2020. Older licenses kept their original `-DCA` number; licenses issued or renewed more recently use the `-DCWP` suffix. Both formats work with `mode=byLicenseNumbers` — just enter the exact number as shown on the license.

# Actor input Schema

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

What to fetch.

## `searchQuery` (type: `string`):

Free-text match against the business's legal name or DBA ("doing business as") trade name. Leave empty with mode=search to browse using only the filters below.

## `licenseNumbers` (type: `array`):

Exact NYC license numbers, e.g. `0002902-DCA` (older format) or `2124913-DCWP` (newer format, issued after the agency was renamed DCA -> DCWP in 2020).

## `phoneNumbers` (type: `array`):

US phone numbers, any format (e.g. `(718) 237-1166` or `7182371166`).

## `businessUniqueIds` (type: `array`):

Exact NYC "Business Unique ID" values, e.g. `BA-1216876-2022`. One business entity can hold several licenses (different categories, renewals, etc.) that all share the same Business Unique ID — this mode returns every license on file for the given ID(s).

## `category` (type: `string`):

Restrict results to a specific licensed business category.

## `borough` (type: `string`):

Restrict results to businesses located in this NYC borough.

## `licenseStatus` (type: `string`):

Restrict results to licenses in this status.

## `licenseType` (type: `string`):

Restrict results to individual license holders or business premises.

## `zipCode` (type: `string`):

Restrict results to this 5-digit NYC ZIP code.

## `addressType` (type: `string`):

Restrict results to how the business address is recorded on file. Most licensed premises use a complete street address; a small share are recorded only as a cross street, a landmark/place name, or a P.O. Box.

## `councilDistrict` (type: `string`):

Restrict results to this NYC City Council district (1-51).

## `communityBoard` (type: `string`):

Restrict results to this NYC Community District Board code.

## `createdAfter` (type: `string`):

Only include licenses first issued on or after this date.

## `createdBefore` (type: `string`):

Only include licenses first issued on or before this date.

## `expiresAfter` (type: `string`):

Only include licenses expiring on or after this date. Combine with License status = Active to find licenses that are currently valid and not expiring soon.

## `expiresBefore` (type: `string`):

Only include licenses expiring on or before this date. Useful for finding licenses that are expired or expiring soon (e.g. for renewal outreach).

## `sortBy` (type: `string`):

Order of results (mode=search).

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

Hard cap on emitted records.

## Actor input object example

```json
{
  "mode": "search",
  "searchQuery": "pizza",
  "licenseNumbers": [],
  "phoneNumbers": [],
  "businessUniqueIds": [],
  "sortBy": "relevance",
  "maxItems": 20
}
```

# Actor output Schema

## `businesses` (type: `string`):

Dataset containing all scraped NYC business license records.

# 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 = {
    "mode": "search",
    "searchQuery": "pizza",
    "licenseNumbers": [],
    "phoneNumbers": [],
    "businessUniqueIds": [],
    "sortBy": "relevance",
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/nyc-business-license-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 = {
    "mode": "search",
    "searchQuery": "pizza",
    "licenseNumbers": [],
    "phoneNumbers": [],
    "businessUniqueIds": [],
    "sortBy": "relevance",
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/nyc-business-license-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 '{
  "mode": "search",
  "searchQuery": "pizza",
  "licenseNumbers": [],
  "phoneNumbers": [],
  "businessUniqueIds": [],
  "sortBy": "relevance",
  "maxItems": 20
}' |
apify call crawlerbros/nyc-business-license-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawlerbros/nyc-business-license-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/Vj0dZV7U7qudgWgfZ/builds/hlXxzHpt2DFdrDP7N/openapi.json
