# Contractor License Aggregator - CSLB California (`punkrecordsdata/contractor-license-aggregator`) Actor

Look up licensed contractors (plumbing, electrical, HVAC and 75 other trades) by ZIP code from the California Contractors State License Board, with classifications, bonding, workers' comp and personnel.

- **URL**: https://apify.com/punkrecordsdata/contractor-license-aggregator.md
- **Developed by:** [PunkRecordsData](https://apify.com/punkrecordsdata) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $21.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.
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

## Contractor License Aggregator - CSLB California

### What does Contractor License Aggregator do?

**Contractor License Aggregator** looks up licensed contractors from the [California Contractors State License Board](https://www.cslb.ca.gov) (CSLB) — the state agency that licenses every construction trade in California, from plumbing and electrical to roofing, solar and welding. Give it one or more ZIP codes and a trade classification, and it returns the licensed businesses in that area with full license detail: entity type, issue/expiration dates, status, trade classifications held, surety bond info, workers' compensation status, and the officers/qualifying individuals behind the license.

No login, no CAPTCHA-solving on your end — the actor handles CSLB's session flow itself. Runs on the Apify platform with API access, scheduling, monitoring, and CSV/Excel/JSON export.

### Why use Contractor License Aggregator?

- **Lead generation** — find licensed plumbers, electricians, HVAC techs or any of CSLB's 78 trade classifications in a target ZIP code, with phone and address ready to call.
- **Vendor/subcontractor vetting** — check a contractor's license status, bond, and workers' comp before hiring them, at scale.
- **Insurance & bonding research** — pull the surety company and bond amount for every active license in a market.
- **Compliance monitoring** — track license expirations and status changes for a list of contractors you already work with.

### How to use Contractor License Aggregator

1. Go to the **Input tab** and enter one or more California ZIP codes.
2. Pick a **trade classification** from the dropdown (all 78 real CSLB classifications — plumbing, electrical, HVAC, roofing, solar, and more).
3. Turn on the extra data you need: **classifications**, **bonding**, **workers' compensation**, **personnel** — each is billed separately, only pay for what you use.
4. Click **Run**. Download results as JSON, CSV, or Excel from the dataset viewer.

### Input

- **ZIP codes** — one or more 5-digit California ZIP codes.
- **Trade classification** — CSLB license classification (e.g. `C-36` Plumbing, `C-10` Electrical, `C-20` HVAC).
- **Max Items** — cap on how many licenses to process (10 on free plan).
- **Classifications / Bonding / Workers' compensation / Personnel** — toggle which extra records to fetch per license.

Example input:

```json
{
    "zipCodes": ["90210"],
    "classification": "C-36",
    "maxItems": 10,
    "includeClassifications": true,
    "includeBonding": true,
    "includeWorkersComp": true,
    "includePersonnel": true
}
```

### Output

The dataset contains up to five record types per license:

- **License record** — business name, address, phone, entity type, issue/expire dates, status.
- **Classification record** — one row per trade classification the license holds.
- **Bonding record** — surety bond company, number, amount, effective date, or exemption.
- **Workers' comp record** — insurance carrier, policy dates, or exemption.
- **Personnel record** — officers and qualifying individuals, with their title/role.

```json
{
    "licenseNumber": "996599",
    "businessName": "MELT CONSTRUCTION INC",
    "address": "1411 TOWER GROVE DRIVE, BEVERLY HILLS, CA 90210",
    "phone": "(310) 993-2319",
    "entity": "Corporation",
    "issueDate": "09/10/2014",
    "expireDate": "09/30/2026",
    "status": "This license is current and active."
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

### Data table

| Field | Description |
| --- | --- |
| `licenseNumber` | CSLB license number |
| `businessName` | Licensed business or contractor name |
| `address` / `phone` | Business address and phone on file |
| `entity` | Corporation, Sole Ownership, Partnership, LLC |
| `issueDate` / `expireDate` | License issue and expiration dates |
| `status` | Current license status (active, expired, suspended, etc. — as published by CSLB) |
| `code` / `description` | Trade classification code and name (classification records) |
| `bonding` | Surety bond details or exemption note |
| `workersComp` | Workers' compensation insurance status or exemption |
| `name` / `title` | Officer/qualifying individual name and role (personnel records) |

### Pricing / Cost estimation

This actor uses **Pay Per Event** pricing — you only pay for the record types you actually request. The base **license record** is the primary event; classifications, bonding, workers' comp and personnel are each optional add-ons priced separately and only charged when you turn them on.

A search that returns 100 licenses with all extras on costs roughly 100 license records plus however many classification/bonding/workers-comp/personnel rows those licenses actually have (most licenses have 1-3 classifications and one officer).

### Tips or Advanced options

- **Turn on only what you need** — each extra toggle is a separate billable event; if you just need business name + status, leave classifications/bonding/workers-comp/personnel off.
- **One ZIP + classification per search** — CSLB's public search returns a bounded list per ZIP/trade combination; run multiple ZIP codes in one input for broader coverage.
- **Schedule it** — combine with Apify scheduling to catch license status or expiration changes over time.

### FAQ, disclaimers, and support

**Is this legal?** This actor only extracts publicly available license information that CSLB itself publishes for consumer protection purposes, respecting the site's normal request patterns.

**Why does `status` vary in wording?** CSLB publishes status as free text (e.g. "This license is current and active.", suspended, expired, revoked) rather than a fixed code — it's passed through as-is rather than force-mapped to an invented enum.

Found a bug or want extra fields (e.g. other states)? Open an issue in the Issues tab or contact us for a **custom scraper** tailored to your sourcing pipeline.

# Actor input Schema

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

California ZIP codes to search for licensed contractors.

## `classification` (type: `string`):

CSLB license classification to search for.

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

Free users: limited to 10 items (preview). Paid users: optional, max 1,000,000.

## `includeClassifications` (type: `boolean`):

All trade classifications held by the license (a license can hold more than one).

## `includeBonding` (type: `boolean`):

Surety bond details or exemption status.

## `includeWorkersComp` (type: `boolean`):

Workers' compensation insurance status.

## `includePersonnel` (type: `boolean`):

Officers and qualifying individuals associated with the license.

## Actor input object example

```json
{
  "zipCodes": [
    "90210"
  ],
  "classification": "C-36",
  "maxItems": 10,
  "includeClassifications": false,
  "includeBonding": false,
  "includeWorkersComp": false,
  "includePersonnel": false
}
```

# Actor output Schema

## `overview` (type: `string`):

Key fields: business name, license number, status

## `fullData` (type: `string`):

Complete dataset including classifications, bonding, workers' comp and personnel rows

# 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 = {
    "zipCodes": [
        "90210"
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("punkrecordsdata/contractor-license-aggregator").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 = {
    "zipCodes": ["90210"],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("punkrecordsdata/contractor-license-aggregator").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 '{
  "zipCodes": [
    "90210"
  ],
  "maxItems": 10
}' |
apify call punkrecordsdata/contractor-license-aggregator --silent --output-dataset

```

## MCP server setup

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

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/gDQoChMhN3iV5vyVW/builds/agWGRAUc3rfRL6mVP/openapi.json
