# US Contractor License Lookup & Lead Lists (WA/OR/TX/NY) (`handa-labs/us-contractor-license-lookup`) Actor

Verify contractors and export license-holder lists from official state registries (Washington L\&I, Oregon CCB, Texas TDLR, New York Contractor Registry). Search by name or license number, filter by trade, city, county, ZIP, status and expiration date. Government open data, no scraping.

- **URL**: https://apify.com/handa-labs/us-contractor-license-lookup.md
- **Developed by:** [tatsuya handa](https://apify.com/handa-labs) (community)
- **Categories:** Lead generation, Business, Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 license records

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?

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

## US Contractor License Lookup & Lead Lists (WA, OR, TX, NY) — official open data

**Verify a contractor's license in seconds, or export a list of licensed contractors by trade, city, ZIP or expiration date** — from the official state registries, not from a third-party directory.

The Actor queries the open-data registries that four state licensing agencies publish and refresh daily:

| State | Registry | What it contains | Records |
|---|---|---|---|
| **WA** | Department of Labor & Industries — Contractor License Data | business, principal, license type & specialties, status, effective/expiration dates, address, phone, UBI | ~160,000 |
| **OR** | Construction Contractors Board — Active Licenses | business, responsible individual, endorsement (residential/commercial level), county, phone, **bond company & amount, insurance company & amount** | ~56,000 |
| **TX** | Department of Licensing and Regulation — All Licenses (contractor & electrician types) | business, owner, license type (A/C contractor, electrical contractor, master/journeyman electrician …), county, expiration | ~100,000 contractor-type |
| **NY** | Department of Labor — Contractor Registry Certificates (public-work contractors) | business, DBA, business type, address, phone, status, issue/expiration, debarment and wage-assessment flags | ~15,000 |

Every record is normalised to one schema, so a multi-state export is a single table.

### Output

```json
{
  "type": "license",
  "state": "OR",
  "source": "Oregon Construction Contractors Board (open data)",
  "sourceDataset": "https://data.oregon.gov/d/g77e-6bhs",
  "licenseNumber": "259647",
  "businessName": "PHENIX ROOFING AND REPAIRS LLC",
  "dbaName": null,
  "principalName": "LEO FRANCIS BRISTOL",
  "licenseType": "Residential General Contractor",
  "specialty": "RGC",
  "status": "ACTIVE",
  "issueDate": "2026-03-11",
  "expirationDate": "2028-03-11",
  "address": "PO BOX 123",
  "city": "LAGRANDE",
  "county": "Union",
  "zip": "97850",
  "phone": "5417866916",
  "bondCompany": "TRAVELERS CASUALTY & SURETY CO OF AMERICA",
  "bondAmount": 25000,
  "insuranceCompany": "AXIS SURPLUS INSE CO",
  "insuranceAmount": 1000000,
  "businessType": null,
  "extra": { "exempt": "Nonexempt", "bondExpDate": "2028-03-11", "insuranceExpDate": "2026-10-01" },
  "checkedAt": "2026-09-04T06:40:00.000Z"
}
```

A `summary` record lists, per state, how many rows were fetched, how many were emitted, and the exact filter that was sent to the registry.

### Why use it

- **Verification** — check that a subcontractor's license is active before you sign, with the registry's own expiration date, bond and insurance details (OR).
- **Lead generation** — insurers, bonding agents, building-material suppliers, software vendors and marketing agencies sell to licensed contractors. Filter by trade and location, export names and phone numbers, load into your CRM.
- **Renewal marketing** — `expiringWithinDays: 60` gives you every license that expires in the next two months (WA, NY server-side; OR, TX client-side).
- **Risk & compliance** — NY flags debarment and outstanding wage assessments.
- **AI agents** — call it as a tool: "Is license ECOSTSC758NN active?" or "List HVAC contractors in Houston".

### How to use

1. Pick the states.
2. Either type a **search** (business name, principal, or license number — 'contains', case-insensitive), an **exact license number**, or leave the search empty and use the **filters** (trade, city, county, ZIP prefix, expiring window).
3. Run. Download JSON / CSV / Excel, or read the dataset through the API.

### Input

```json
{
  "states": ["WA", "OR"],
  "licenseType": "ROOF",
  "zip": "98",
  "activeOnly": true,
  "expiringWithinDays": 0,
  "maxRecordsPerState": 1000
}
```

| Field | Default | Meaning |
|---|---|---|
| `states` | all four | WA, OR, TX, NY |
| `query` | — | contains-search across business, principal/owner and license number |
| `licenseNumber` | — | exact license / certificate number |
| `licenseType` | — | contains-match on type, specialty and endorsement fields (GENERAL, ELECTRICAL, PLUMBING, HVAC, ROOFING…). Texas defaults to contractor and electrician types. |
| `city` / `county` / `zip` | — | exact city, exact county (OR, TX), ZIP prefix |
| `activeOnly` | true | drop inactive / expired licenses |
| `expiringWithinDays` | 0 | keep only licenses expiring within N days |
| `maxRecordsPerState` | 1000 | cap per state (unfiltered exports are capped at 5,000) |
| `socrataAppToken` | — | optional free token to raise rate limits for very large exports |

### Pricing

Pay-per-event: a small fee per run plus a fee per license record returned. A verification of one license costs one record; a 1,000-contractor lead list costs 1,000 records.

### Coverage notes & roadmap

- Fields differ by state: Texas publishes no address or phone; Oregon publishes bond and insurance; New York publishes compliance flags.
- Data is exactly what the agency publishes; check the `sourceDataset` link for the registry's own disclaimer. These are public records intended for verification and business use. Do not use them for consumer credit, employment or tenant screening decisions (FCRA).
- On the roadmap: California (CSLB public data portal), Florida (DBPR public-records extracts), Arizona ROC, Nevada NSCB. Vote by opening an issue on the Actor page.

***

### 日本語

米国4州(ワシントン・オレゴン・テキサス・ニューヨーク)の州政府が公開している建設業者ライセンス登録簿を横断検索し、1つのスキーマに正規化して返します。用途はライセンスの真偽確認と、業種・地域・有効期限で絞った営業リストの作成(保険・ボンド・建材・ソフトウェアの営業先)。データは各州のオープンデータAPIから直接取得しており、スクレイピングではありません。

# Actor input Schema

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

Which state registries to query.

## `query` (type: `string`):

Case-insensitive 'contains' search across business name, principal/owner name and license number. Leave empty to export lists using the filters below.

## `licenseNumber` (type: `string`):

Exact match. Use for verification of a single contractor.

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

e.g. GENERAL, ELECTRICAL, PLUMBING, HVAC, A/C CONTRACTOR, ROOFING. Matched against the registry's type, specialty and endorsement fields. Texas defaults to contractor and electrician licence types when empty.

## `city` (type: `string`):

City name as recorded by the registry (e.g. SEATTLE).

## `county` (type: `string`):

County name (Oregon, Texas).

## `zip` (type: `string`):

ZIP code prefix, e.g. 981 for Seattle area.

## `activeOnly` (type: `boolean`):

Exclude inactive, suspended or expired licences where the registry exposes a status.

## `expiringWithinDays` (type: `integer`):

Only licences whose expiration date falls within the next N days — a renewal-marketing list for insurers, bonding agents and continuing-education providers. 0 = no filter.

## `maxRecordsPerState` (type: `integer`):

Safety cap per state registry (unfiltered exports are capped at 5,000).

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

Free token from any Socrata portal (e.g. data.wa.gov) to lift the anonymous rate limit for large exports.

## Actor input object example

```json
{
  "states": [
    "WA",
    "OR",
    "TX",
    "NY"
  ],
  "query": "ROOFING",
  "activeOnly": true,
  "expiringWithinDays": 0,
  "maxRecordsPerState": 1000
}
```

# 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 = {
    "query": "ROOFING"
};

// Run the Actor and wait for it to finish
const run = await client.actor("handa-labs/us-contractor-license-lookup").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 = { "query": "ROOFING" }

# Run the Actor and wait for it to finish
run = client.actor("handa-labs/us-contractor-license-lookup").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 '{
  "query": "ROOFING"
}' |
apify call handa-labs/us-contractor-license-lookup --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,handa-labs/us-contractor-license-lookup"
        }
    }
}

```

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/HFtGQlHeihoKP0HIH/builds/PzREScPRkpjzyvSRQ/openapi.json
