# California Construction Trades Directory & Leads (CSLB) (`scrapebench/california-construction-trades-directory`) Actor

Sweep every construction trade across every California county you pick, in one run. Deduplicated licensed-contractor leads from the official CSLB register — name, address, phone, licence, bond and workers' comp.

- **URL**: https://apify.com/scrapebench/california-construction-trades-directory.md
- **Developed by:** [ScrapeBench](https://apify.com/scrapebench) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.002 / 13 building trades across sonoma, napa, solano and contra costa counties

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/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

## California Construction Trades Directory & Leads (CSLB)

### Pain points

- Building a regional contractor list means running one search per trade per county — thirteen trades across four counties is fifty-two separate searches, then a manual merge.
- The same contractor holds several classifications, so merging those searches by hand leaves duplicates that inflate your list and your outreach.
- CSLB's own export gives you one classification and one county at a time, with no way to say 'every building trade in the North Bay'.

### What we solve

- One run takes a list of trades and a list of counties and returns the whole sweep.
- Every county you ask for is fetched in a single request per trade, so widening the geography costs no extra requests and no extra time.
- Results are deduplicated by licence number before you are charged — a contractor holding three of your trades is one row and one charge.
- Each row is tagged with which of your requested trades matched, while still listing every classification that contractor holds.

### Summary

Pick your trades, pick your counties, get one clean construction-contractor list for the whole region — deduplicated, billed once per contractor, straight from California's official licence register.

### Who it's for

- Building-material suppliers and distributors prospecting contractors in a sales territory
- Trade-focused staffing and recruiting firms mapping licensed contractors by region
- Insurance and surety brokers targeting contractors by bond and workers' comp status
- Agencies and RevOps teams building regional construction lead lists for outbound

### How to use

Set the input, run the actor, and collect results from the run's dataset (export to JSON/CSV/Excel, or pull via the Apify API). Example input:

```json
{
  "licenseClasses": [
    "B",
    "C-10",
    "C-20",
    "C-27",
    "C-36",
    "C-39"
  ],
  "counties": [
    "Sonoma",
    "Napa",
    "Solano",
    "Contra Costa"
  ],
  "maxResults": 500
}
```

See **Inputs** below for every available field.

### What you get

One row per record:

| Field | Description |
|---|---|
| `license_number` | CSLB licence number |
| `business_name` | Licensed business name |
| `matched_trade` | Which of your requested trades this contractor was found under |
| `business_type` | Sole Owner, Corporation, LLC, Partnership… |
| `address` | Business street address |
| `city` | City |
| `county` | California county |
| `zip_code` | ZIP code |
| `phone` | Business phone as CSLB holds it |
| `classifications` | Every classification this contractor holds, not just the one you searched |
| `status` | Licence status, e.g. CLEAR |
| `issue_date` | Licence issue date |
| `expiration_date` | Licence expiry date |
| `surety_company` | Contractor bond surety company |
| `bond_number` | Contractor bond number |
| `workers_comp_type` | Workers' comp coverage type or exemption |
| `workers_comp_company` | Workers' comp insurance carrier |
| `source_url` | CSLB licence detail page for this contractor |

Sample:

```json
{
  "license_number": "975545",
  "business_name": "TAYLOR ENERGY SYSTEMS INC",
  "matched_trade": "C-46",
  "business_type": "Corporation",
  "address": "7171 EVAN AVENUE",
  "city": "SEBASTOPOL",
  "county": "Sonoma",
  "zip_code": "95472",
  "phone": "(707) 494 6053",
  "classifications": [
    "C10",
    "C46"
  ],
  "status": "CLEAR",
  "issue_date": "08/03/2012",
  "expiration_date": "08/31/2028",
  "surety_company": "AMERICAN CONTRACTORS INDEMNITY COMPANY",
  "bond_number": "100201394",
  "workers_comp_type": "Workers' Compensation Insurance",
  "workers_comp_company": "STATE COMPENSATION INSURANCE FUND",
  "source_url": "https://www.cslb.ca.gov/onlineservices/checklicenseII/LicenseDetail.aspx?LicNum=975545"
}
```

### Inputs

| Field | Required | Type | Default | Description |
|---|---|---|---|---|
| `licenseClasses` | no | array | `["B", "C-5", "C-8", "C-9", "C-10", "C-15", "C-20", "C-27", "C-33", "C-35", "C-36", "C-39", "C-43"]` | The CSLB trades to sweep. Defaults to the 13 building trades most lead lists want — general building plus framing, concrete, drywall, electrical, flooring, HVAC, landscaping, painting, plastering, plumbing, roofing and sheet metal. Add or remove any code you like: A, B, B-2, C-2 … C-60, and the C-61/D-xx limited specialties (e.g. 'C-46' solar, 'C-53' swimming pool, 'C-61/D-49' tree service). Each trade is one request; a contractor holding two of your trades is returned — and billed — once. |
| `licenseClass` | no | string | — | One CSLB classification code, added to whatever is in 'Construction trades'. Here so a saved task built around a single trade keeps working; most runs should use the list above. |
| `counties` | no | array | `["Sonoma", "Napa", "Solano", "Contra Costa"]` | California counties to sweep, e.g. Sonoma and Napa and Solano. ALL of them are fetched in a single request per trade, so adding counties costs no extra requests. Case, spacing and a trailing 'County' do not matter. Turn on Discovery Mode to list every valid name. |
| `county` | no | string | — | One California county, added to whatever is in 'Counties'. Here so a saved task built around a single county keeps working. |
| `maxResults` | no | integer | — | Cap on records returned PER TRADE (each trade is one download covering all your counties), not per run — so adding trades can never silently truncate the ones later in the list. Leave empty to return everything. A wide trade list across large counties can return tens of thousands of rows; set this if you want a bounded bill. |
| `listCountiesOnly` | no | boolean | `false` | If true, skip the sweep and return every valid California county name from the live CSLB form. Free — not charged. Use it to check spellings before a real run. |
| `proxyConfiguration` | no | object | `{"useApifyProxy": false}` | Optional, and off by default. CSLB answers Apify's platform IPs directly — measured 2026-08-19 — so a proxy is not needed and only adds latency. Enable one only if a run returns no data and the log shows CSLB refusing the request. |

### Pricing (Pay Per Event)

You pay per result (`dataset-item`) — **no charge for empty runs**. Example: **2400 13 building trades across Sonoma, Napa, Solano and Contra Costa counties** at *$0.002/result* ≈ **$4.80**.

Charged per deduplicated contractor, so a contractor holding several of your trades costs you once. A wide trade list across large counties returns tens of thousands of rows — set 'Maximum results per trade' if you want a bounded bill. Apify platform usage (compute) is billed separately per your plan.

### Use cases

- Build a territory list of every licensed building trade across a metro area in one run
- Segment prospects by trade using matched\_trade while keeping each contractor's full classification set
- Filter for contractors whose workers' comp is an exemption rather than a policy, for insurance outreach
- Refresh a regional contractor list on a schedule and diff it to spot new licences

### Why this actor

- One run instead of one per trade per county — the sweep this actor is built for takes 8 requests where a per-pair approach takes 56.
- Deduplicated before charging, so overlapping classifications never bill you twice for the same contractor.
- Straight from California's official CSLB register — the same data the state publishes, parsed into a clean, typed dataset.

### Limitations & updates

Covers California only, and only what the CSLB register publishes — there are no email addresses in the source, and inactive or expired licences appear with their status rather than being filtered out. Contact details are the business details CSLB holds on file, which can lag a contractor's current website.

### FAQ

**What does one run return?**

Every active licensed contractor holding any of your chosen trades in any of your chosen California counties, deduplicated by licence number, with business, contact, classifications, bond and workers' comp details.

**How is this different from the California Contractor Directory actor?**

That actor is built around one trade and one county at a time and is unchanged. This one is built for the sweep: give it a list of trades and a list of counties and it returns the whole region in a single run, deduplicated across trades.

**Which trades can I ask for?**

Any CSLB classification — A, B, B-2, the C-2 to C-60 specialty trades, and the C-61/D-xx limited specialties such as C-61/D-49 tree service. The default is the thirteen building trades most lead lists want; edit the list to suit.

**Am I charged twice for a contractor who holds two of my trades?**

No. Results are deduplicated by licence number before charging, so each contractor is one row and one charge no matter how many of your trades they hold.

**What happens if I mistype a county?**

Nothing fails. Case, spacing and a trailing 'County' are all handled, and anything still unrecognised is logged and skipped. If none of your counties resolve, the run returns the free county list so you can see the exact spellings.

**Does it need a proxy?**

No. CSLB answers Apify's platform IPs directly, so the proxy is off by default. The option is there if you ever need it, but enabling it only adds latency.

### Which actor to choose

Three CSLB actors, three different jobs:

- **California Contractor Directory by Trade & County (CSLB)** — You want one trade in one county, or you already have a saved task built that way.
- **California Contractor License Lookup & Verify (CSLB)** — You want to verify specific contractors by licence number or business name, rather than build a list.

### Guides & use cases

Written up on **[scrapebench.dev](https://scrapebench.dev)** — the bench that runs and verifies this actor against the live source every night:

- **How-to:** [How to run California Construction Trades Directory & Leads (CSLB)](https://scrapebench.dev/guides/how-to-california-construction-trades-directory/)
- **Use case:** [Build a regional construction lead list in one run](https://scrapebench.dev/use-cases/build-a-regional-construction-lead-list/)

More actors, coverage and nightly verification results: **[scrapebench.dev](https://scrapebench.dev)**

# Actor input Schema

## `licenseClasses` (type: `array`):

The CSLB trades to sweep. Defaults to the 13 building trades most lead lists want — general building plus framing, concrete, drywall, electrical, flooring, HVAC, landscaping, painting, plastering, plumbing, roofing and sheet metal. Add or remove any code you like: A, B, B-2, C-2 … C-60, and the C-61/D-xx limited specialties (e.g. 'C-46' solar, 'C-53' swimming pool, 'C-61/D-49' tree service). Each trade is one request; a contractor holding two of your trades is returned — and billed — once.

## `licenseClass` (type: `string`):

One CSLB classification code, added to whatever is in 'Construction trades'. Here so a saved task built around a single trade keeps working; most runs should use the list above.

## `counties` (type: `array`):

California counties to sweep, e.g. Sonoma and Napa and Solano. ALL of them are fetched in a single request per trade, so adding counties costs no extra requests. Case, spacing and a trailing 'County' do not matter. Turn on Discovery Mode to list every valid name.

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

One California county, added to whatever is in 'Counties'. Here so a saved task built around a single county keeps working.

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

Cap on records returned PER TRADE (each trade is one download covering all your counties), not per run — so adding trades can never silently truncate the ones later in the list. Leave empty to return everything. A wide trade list across large counties can return tens of thousands of rows; set this if you want a bounded bill.

## `listCountiesOnly` (type: `boolean`):

If true, skip the sweep and return every valid California county name from the live CSLB form. Free — not charged. Use it to check spellings before a real run.

## `proxyConfiguration` (type: `object`):

Optional, and off by default. CSLB answers Apify's platform IPs directly — measured 2026-08-19 — so a proxy is not needed and only adds latency. Enable one only if a run returns no data and the log shows CSLB refusing the request.

## Actor input object example

```json
{
  "licenseClasses": [
    "B",
    "C-5",
    "C-8",
    "C-9",
    "C-10",
    "C-15",
    "C-20",
    "C-27",
    "C-33",
    "C-35",
    "C-36",
    "C-39",
    "C-43"
  ],
  "licenseClass": "C-39",
  "counties": [
    "Sonoma",
    "Napa",
    "Solano",
    "Contra Costa"
  ],
  "county": "Sacramento",
  "listCountiesOnly": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `contractors` (type: `string`):

Every contractor found - licence #, business, contact, all classifications held, bond and workers' comp, plus which of your trades matched.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapebench/california-construction-trades-directory").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("scrapebench/california-construction-trades-directory").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 '{}' |
apify call scrapebench/california-construction-trades-directory --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapebench/california-construction-trades-directory"
        }
    }
}

```

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/6nfPvNbDaJmWGSdjS/builds/kMPVktRPKN4FDpZCR/openapi.json
