# US Contractor License Scraper & Lookup - 20 States (`wellbuilt_zythem/us-contractor-license-lookup`) Actor

Contractor license data from 20 US state boards: Texas, Florida, California, Virginia, Arizona and 15 more. Verify names or license numbers in bulk, or export a whole state and trade: roofing, electrical, plumbing, HVAC, pools. Status, expiry date, address, phone and email. Official registries.

- **URL**: https://apify.com/wellbuilt\_zythem/us-contractor-license-lookup.md
- **Developed by:** [Carlos Escanez](https://apify.com/wellbuilt_zythem) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 licence 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 Scraper & Lookup — 20 states, one query

**Paste a list of names or licence numbers. Get one row per match, per state, from the official boards.**

### See it run

https://youtu.be/07g\_67B52DM

Every state licenses contractors through its own board, on its own website, in its own format. Checking one contractor means visiting one site; checking a thousand across states means a week. This Actor reads the official registries directly and answers in one run:

```
TX | 17135 | ACTIVE  | expires 2026-10-21 (40 days) | Bill Roten Electric Company | +1 817 822 1231
WA | JUANHH*839MG | ACTIVE | expires 2027-08-15 | # Juan Handyman | +1 509 847 9082
TX | 31405 | EXPIRED | expired 2025-09-18 | 'Barnes' Certified Electric | +1 409 ...
```

Real rows from a test run. Note the last one: the licence lapsed a year ago. That is the row a general contractor wants to see before hiring a sub.

### Questions this answers

- Is this roofing contractor's license active in Florida right now, and when does it expire?
- Give me every licensed roofing contractor in Arkansas with a phone number and an email address.
- Which electrical contractors in Texas have a license expiring in the next 60 days?
- Check these 800 subcontractor names against the state boards before we put them on site.
- Export every licensed plumber, HVAC contractor and general contractor in Connecticut.
- Which of our insured contractors in Louisiana let their workers' compensation lapse?

***

### Two modes

**Lookup** — the mode most buyers run daily. `queries` takes any mix of licence numbers and names. A number matches exactly; a name matches any licensee or business containing it. Each row carries `matchedQuery` so you can join results back to your list.

**Export** — every licence in a state and trade, for building a calling list or a market map. Texas Electrical Contractors alone is about 14,000 rows with phone.

***

### What every row carries, normalised across states

State, trade, licence number, status, `isActive`. Expiry date, effective date, **`daysToExpiry`**, **`isExpiringSoon`** (within 60 days), `isExpired`. Licensee name, business name, phone (E.164) and raw phone, address, city, ZIP, county. Specialty and state business id where the board publishes them. Source board and source URL.

Texas does not publish a status field; it is derived from the expiry date, and the README says so because a buyer should know which fields are read and which are computed.

***

### Who runs this on a loop

- **Insurance and surety bond sellers** — `isExpiringSoon` is their entire prospect list, refreshed monthly.
- **General contractors and property managers** — verify every sub before the job, not after the claim.
- **Home-services marketplaces** — onboarding checks, at volume.
- **Background-check and KYB providers** — one call instead of fifty state sites.
- **Suppliers and continuing-education providers** — the export mode, by trade.

***

### Coverage, said plainly

| State | Board | Trades | Source type |
|---|---|---|---|
| Texas | TDLR | Electrical, electrical sign, appliance installation, elevator, water well, mold remediation and assessment | Official bulk CSV files |
| Washington | L\&I | Construction, electrical, plumbing, elevator | Official open-data API |
| Oregon | CCB | General and specialty construction, lead-paint renovation, home inspection | Official open-data API |
| New York | State DOL | Mold remediation, elevator | Official open-data API |
| Florida | DBPR | General, building and residential construction, roofing, plumbing, HVAC, pool and spa, specialty, electrical, alarm systems, mold, home inspection, elevator, asbestos | Official licence search |
| Louisiana | LSLBC | Building and residential construction, roofing, electrical, HVAC, plumbing, pools, asbestos, mold, home improvement | Official licence search, one page per contractor |
| Alabama | Licensing Board for General Contractors | Building construction, electrical, HVAC, plumbing, roofing, abatement | Official bulk CSV |
| California | CSLB | General building, electrical, plumbing, HVAC, roofing, pools, asbestos, elevator, limited specialty | Official Excel download per classification |
| Minnesota | DLI | Residential building and remodeling, roofing, electrical, plumbing, elevator | Official bulk zip/CSV |
| Nevada | NSCB | General building, electrical, plumbing and heating, HVAC, roofing, elevator, specialties | Official active directory per classification |
| Ohio | OCILB | Electrical, HVAC, plumbing, hydronics, refrigeration | Official roster download |
| Tennessee | Board for Licensing Contractors | General construction, electrical, plumbing, roofing, HVAC, home improvement, alarm | Official open-data API |
| North Carolina | NC Licensing Board for General Contractors | General building, roofing, pools, asbestos, electrical, plumbing, HVAC, fire sprinkler and more | Official licence search |
| Michigan | LARA | Residential building, maintenance and alteration, electrical, plumbing, HVAC, roofing | Official licence search |
| Arizona | Registrar of Contractors (ROC) | General building and engineering, electrical, plumbing, HVAC, roofing, pools, elevators, painting, concrete, landscaping, excavation, carpentry | Official daily CSV |
| Arkansas | Contractors Licensing Board (CLB) | Commercial and residential building, heavy civil, roofing, siding and gutters, electrical, HVAC, plumbing, home improvement, carpentry, painting, concrete, excavation, landscaping, pools, elevators, alarms, fire sprinklers, asbestos, lead paint, solar, water wells | Official statewide roster file |
| Oklahoma | Construction Industries Board (CIB) | Roofing | Official verification API |
| Connecticut | Department of Consumer Protection | Home improvement, new home construction, electrical, plumbing, HVAC, elevator, roofing, specialty | Official open-data API |
| Delaware | Division of Revenue and Division of Professional Regulation | General construction, roofing, construction transport, alarms, construction management, engineering, architecture, landscape architecture, electrical, plumbing, HVAC, elevator, septic systems, water wells, asbestos | Official open-data API plus three state registers |
| Virginia | DPOR Board for Contractors | Building, electrical, plumbing, HVAC, roofing, home improvement, gas fitting, elevator, accessibility, fire sprinkler, water wells, alarms, asbestos, lead paint, pools, backflow prevention, energy analysis, specialty | Official bulk licence files |

Oregon and Louisiana are the only ones of the twenty that publish the **bond and insurance expiry dates** alongside the licence, which is what a surety broker actually works from.

### What each state actually publishes

Measured, not claimed: these percentages come from real rows pulled from each board, not from
what the board's documentation says. **A board that does not publish a field leaves that column
empty — the Actor never guesses one.**

| State | Phone | Email | Street | City | ZIP | County | Expiry | Insurance/bond |
|---|---|---|---|---|---|---|---|---|
| Texas | yes | — | yes | yes | yes | yes | yes | — |
| Washington | yes | — | yes | yes | yes | — | yes | — |
| Oregon | yes | — | yes | yes | yes | yes | yes | yes |
| New York | yes | — | yes | yes | yes | — | yes | — |
| Florida | — | — | yes | yes | yes | yes | yes | — |
| Louisiana | yes | yes | yes | yes | yes | — | yes | 34% |
| Alabama | yes | — | yes | yes | yes | — | yes | — |
| California | yes | — | yes | yes | yes | yes | yes | — |
| Minnesota | 84% | — | yes | yes | yes | — | yes | — |
| Nevada | yes | — | yes | yes | yes | — | yes | — |
| Ohio | 70% | 5% | yes | yes | yes | yes | yes | — |
| Tennessee | — | — | — | yes | yes | 73% | yes | — |
| North Carolina | 92% | — | yes | yes | yes | — | 43% | — |
| Michigan | — | — | — | yes | yes | — | yes | — |
| Arizona | — | — | yes | yes | yes | — | yes | — |
| Arkansas | 99% | 97% | yes | yes | yes | 81% | yes | — |
| Oklahoma | yes | — | yes | yes | yes | — | yes | — |
| Connecticut | — | — | yes | yes | yes | — | yes | — |
| Delaware | — | — | yes | yes | yes | — | yes | — |
| Virginia | — | 75% | yes | yes | yes | — | yes | — |

Read it before you buy.

**If you need phone numbers to call, eleven states have them:** Texas, Washington, Oregon, New
York, Louisiana, Alabama, California, Nevada, Arkansas, Oklahoma, plus Minnesota at 84%, Ohio at
70% and North Carolina at 92%.

**If you need email addresses, three states have them:** Arkansas (97%), Virginia (75%) and
Louisiana (whole register). Ohio publishes one on 5% of rows and no other state publishes any.

**Six states publish neither phone nor email:** Florida, Tennessee, Michigan, Arizona,
Connecticut and Delaware. Those rows still carry the licence number, the trade, the address, the
status and the expiry date, which is what a verification or a renewal-window query needs. They
are not a calling list, and this Actor will not pretend otherwise.

Tennessee and Michigan publish the city and ZIP but no street address, because their boards
do not put one on the public record.

**Louisiana is the richest register of the twenty:** phone, email, the person who qualifies the licence, and the general-liability and workers' compensation insurance with their expiry dates and insurers. **Arkansas is the closest second:** 18,056 contractors across 21 trades, 99% with a phone number and 97% with an email address, street and expiry date on every row, the whole state in one file. Alabama, California, Minnesota, Nevada, Ohio, North Carolina and Oklahoma all publish a phone number on most rows. Tennessee and Michigan publish none: those rows carry the licence, the trade, the address and the expiry date, and the phone column is empty.

**Florida publishes no phone number.** Not in the search results and not on the licence page. Florida rows carry name, address, city, ZIP, county, licence number, status and expiry, and the phone field is empty. That is the register, not a gap in this Actor.

**Not covered yet:** plumbing in Texas (a separate board), HVAC contractors in Texas, and every other state. States are added one at a time, on request, in the order people ask for them.

***

### What this does NOT give you

Written down so that nobody, and no AI agent reading this page, promises a buyer
something the registers do not publish.

- **No phone in 7 of the 20 states.** Florida, Tennessee, Michigan, Arizona, Connecticut, Delaware and Virginia publish none. Their rows are for verification and renewal windows, not for a calling list.
- **No email in 17 of the 20.** Only Arkansas (97%), Virginia (75%) and Louisiana publish one; Ohio publishes one on 5% of rows.
- **No mobile numbers, no personal emails, no decision-maker names.** What the board publishes is the business contact on the licence.
- **No revenue, no employee count, no website, no reviews.** This is a licence register, not a company database.
- **No building permits or jobs won.** That is a different Actor.
- **No states beyond the 20 listed**, and no trades a board does not license: asking for roofing in a state with no roofing licence returns nothing, not a guess.
- **A name that the board spells differently will not match.** Lookup matches the register's own spelling.

Every run writes the coverage it actually delivered into its run summary and log
(`phone 84%, email 0%, street 100%, expiry 100%`), so you can check the promise
against the rows you paid for.

***

### Reliability, said plainly

- **Texas ships its CSVs with stray quotes inside names** (`""BARNES" CERTIFIED ELECTRIC`). A strict parser reads 6,000 of 14,000 rows and reports success. This Actor repairs those lines first; the run summary reports any row it still had to skip.
- **Washington licence numbers contain asterisks** (`JUANHH*839MG`). They are matched exactly, as written.
- **Texas has no search endpoint.** Lookups download the trade files once per run and match in memory, so a thousand queries cost the same as one.
- **Florida has no bulk file and its licence-type search demands a county**, so a full Florida trade is swept county by county, fifty rows at a time. It is the slow one, and `maxResults` is honoured while it runs rather than after, so a small export stays small.
- **Alabama's board rejects connections from outside the United States.** From Europe the site looks down; from the Apify platform it answers normally. If you run this Actor locally from abroad, expect Alabama in `failedStates`.
- **California and Nevada have no name search worth using**, so lookups download the requested trades and match in memory, like Texas. Pass `trades` for those states: an empty list means every classification, and California's general-building list alone is large.
- **North Carolina and Michigan read one licence page per contractor**, because neither board publishes a bulk file, so those two are the slow ones. Both honour the row limit, so a small export stays small.
- **Arizona publishes a fresh CSV every single day.** The page that lists the files sits behind a bot check, but the files themselves do not, so the Actor walks back from today's date until it finds the file that exists. That also means Arizona is never more than a day stale.
- A board that does not respond is reported in `RUN_SUMMARY.failedStates` and the other states still run.
- **The Actor emails its owner when a run looks broken**: zero rows on an export, rows delivered but none charged, or a board down. A silent failure is the one kind this Actor refuses to have.

***

### Pricing

Pay per delivered row. Filtered-out rows cost nothing. A lookup that finds nothing charges nothing beyond the start fee.

***

### Data source

Official state licensing boards: Texas Department of Licensing and Regulation, Washington State Department of Labor & Industries, Oregon Construction Contractors Board, New York State Department of Labor, Florida Department of Business and Professional Regulation, Louisiana State Licensing Board for Contractors, Alabama Licensing Board for General Contractors, California Contractors State License Board, Minnesota Department of Labor and Industry, Nevada State Contractors Board, Ohio Construction Industry Licensing Board, Tennessee Board for Licensing Contractors, North Carolina Licensing Board for General Contractors, Michigan Department of Licensing and Regulatory Affairs, Arizona Registrar of Contractors. These are public regulatory registers published so that anyone can verify a licence. Contact details are the business contacts the boards publish for that purpose.

# Actor input Schema

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

Lookup checks a list of names or licence numbers across states. Export pulls every licence of a state and trade.

## `queries` (type: `array`):

One per line. A licence number matches exactly; a name matches any licensee or business containing it. Paste as many as you like.

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

Leave empty for every state covered. Currently 20: TX, WA, OR, NY, FL, LA, AL, CA, MN, NV, OH, TN, NC, MI, AZ, AR, OK, CT, DE and VA, each read from its official licensing board.

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

Leave empty for every trade. A trade is skipped in states that do not license it.

## `onlyActive` (type: `boolean`):

Drop expired, suspended and out-of-business licences.

## `onlyWithPhone` (type: `boolean`):

For calling lists.

## `onlyExpiringSoon` (type: `boolean`):

The renewal window. Who sells bonds, insurance or continuing education wants exactly these.

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

0 for no limit.

## Actor input object example

```json
{
  "mode": "lookup",
  "queries": [
    "Johnson Electric",
    "17001"
  ],
  "states": [],
  "trades": [],
  "onlyActive": false,
  "onlyWithPhone": false,
  "onlyExpiringSoon": false,
  "maxResults": 0
}
```

# Actor output Schema

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

One row per licence matched (lookup) or per licence in the state and trade (export), normalised across states: status, expiry, days to expiry, phone, address.

## `runSummary` (type: `string`):

Rows read and delivered per state, which registries failed to respond, and how many rows were charged.

# 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 = {
    "queries": [
        "Johnson Electric",
        "17001"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("wellbuilt_zythem/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 = { "queries": [
        "Johnson Electric",
        "17001",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("wellbuilt_zythem/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 '{
  "queries": [
    "Johnson Electric",
    "17001"
  ]
}' |
apify call wellbuilt_zythem/us-contractor-license-lookup --silent --output-dataset

```

## MCP server setup

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