# CA Contractor Licenses - CSLB Register (Bonds + Discipline) (`j0401/ca-cslb-contractors`) Actor

California CSLB contractor license register (243k+ license rows): search by name, city, county, zip, status or license class, look up one license for its full record, and screen suspensions. Carries the surety-bond triple, workers comp coverage and discipline cases.

- **URL**: https://apify.com/j0401/ca-cslb-contractors.md
- **Developed by:** [Wenhao Yang](https://apify.com/j0401) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.03 / 1,000 california contractor 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

## California Contractor Licenses - CSLB Register (Bonds + Discipline)

The complete California Contractors State License Board register: **243,786
contractor licenses**, refreshed daily from CSLB's official Statewide Public
Database Files. Every license carries the full surety-bond triple, workers'
comp coverage, license classes and discipline cases.

### Low cost

**From $0.00005 per record, down to $0.00003 at Gold.** Pay only for the records
you actually receive - the whole register stays queryable, you are never billed
for the scan behind it.

### Screen a contractor before you hire

`primaryStatus=CLEAR` (231,014 licenses, 94.8%) is the healthy value. The other
20 values are suspension codes - the signal that matters:

| status | licenses |
|---|---|
| CLEAR | 231,014 |
| Contr Bond Susp | 7,953 |
| Work Comp Susp | 2,957 |
| Liab Ins Susp | 504 |
| Judgement Susp | 138 |
| Family Sup Susp | 187 |
| 15 more codes | |

Set `status` to any one, or `hasDiscipline=true` for the 1,817 licenses carrying
an actual discipline case (`dbCaseNo` / `discpCaseRegion`).

### Search it

- **Name** - `businessName="DOCKERY"` (substring over the legal + full + DBA
  names, case-insensitive).
- **Where** - `city`, `county`, `zipCode` (prefix).
- **Class** - `classification="B"` (General Building), `"C10"` (Electrical),
  `"C36"` (Sheet Metal). Matches a **full class token**, so `"B"` does not also
  return `"C10"` or `"HB"`.
- **Form** - `businessType`: Sole Owner (113,973), Corporation (111,706),
  Limited Liability (14,074), Partnership, JointVenture.
- **Exact id** - `licenseNumber` (a number identifies exactly one license).
- **Discipline** - `hasDiscipline=true`.

### Example inputs

**Suspended contractors in one county** - the pre-hire screen.

```json
{ "county": "Los Angeles", "status": "Work Comp Susp", "maxResults": 50 }
```

**One license, in full** - every bond, policy and discipline field.

```json
{ "mode": "profile", "licenseNumber": "1000002" }
```

**General Building contractors in Los Angeles** - class filter is a full token.

```json
{ "county": "Los Angeles", "classification": "B", "maxResults": 25 }
```

**Counts by license status** - `mode=aggregate`.

```json
{ "mode": "aggregate", "groupBy": "primaryStatus" }
```

### Or roll it up

`mode=aggregate` returns one count row per group - **business type**, **primary
status**, **county**, **workers' comp coverage** or **mailing state**. Every
group comes back; this mode is not cut off by `maxResults`.

```
Los Angeles   49,728
San Diego     21,615
Orange        20,155
Riverside     16,551
...
```

### Example output

**One contractor** - `mode=profile`:

```json
{
 "platform": "ca-cslb",
 "licenseNumber": "1000002",
 "businessName": "DOCKERY RANDALL MARK",
 "fullBusinessName": "RANDALL MARK DOCKERY",
 "businessType": "Sole Owner",
 "primaryStatus": "CLEAR",
 "classifications": "C57",
 "city": "LODI",
 "county": "San Joaquin",
 "zipCode": "95242",
 "businessPhone": "(925) 383 0487",
 "issueDate": "2015-01-10",
 "expirationDate": "2027-01-31",
 "workersCompCoverageType": "Exempt",
 "cbSuretyCompany": "PHILADELPHIA INDEMNITY INSURANCE COMPANY",
 "cbNumber": "PB10163403900",
 "cbAmount": "25000",
 "cbEffectiveDate": "2025-09-14",
 "cbCancellationDate": "2026-10-21"
}
```

### Also: the change feed

`mode=changes` returns the diff between the last two daily snapshots - licenses
added, removed, or with any field changed (new bonds, suspensions, address
moves). Each row carries `changeType` (added / removed / updated), and for
`updated` rows the `changedFields` list and the previous `oldValues`. This is
the daily-tracking surface.

### Notes on the data, from the source

- **One row = one license.** `licenseNumber` is unique - this is not a
  per-person register.
- **`classifications` is a list.** A contractor can hold several classes
  (`"B, C10"`); the `classification` filter matches a single token inside that
  list.
- **Bond and insurance fields are the deep part.** `cb*` (Contractor Bond),
  `wb*` (Working-Water-Well Bond) and `db*` (Disciplinary Bond) each carry the
  surety company, bond number, amount and effective/cancel dates; `wc*` carries
  the workers' comp company, policy and dates. Coverage varies - a bond is only
  populated where one is required.
- **Discipline is rare and real.** 1,817 licenses carry a discipline case; the
  rest have blank discipline fields.

# Actor input Schema

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

search = filter the register. profile = one license's full record (needs licenseNumber). aggregate = one row per group. changes = the feed between the last two daily snapshots. Leave blank to auto-route.

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

Exact CSLB license number, e.g. "1000002" or "724677". With this set (and no other filter), returns that contractor's full record.

## `businessName` (type: `string`):

Business or contractor name, substring, case-insensitive (e.g. "DOCKERY" or "SOUTH COAST").

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

Mailing city, substring, case-insensitive (e.g. "Los Angeles").

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

County name, substring, case-insensitive (e.g. "Los Angeles", "Orange").

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

ZIP code prefix (digits only), e.g. "900" for Los Angeles.

## `status` (type: `string`):

License status. Blank = all. CLEAR is the healthy value (~94.8%); everything else is a suspension code - the most useful pre-hire screening signal.

## `businessType` (type: `string`):

Legal form of the contractor. Blank = all.

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

A CSLB license class token, e.g. "B" (General Building), "C10" (Electrical), "C36" (Sheet Metal). Matches a full class token exactly (no hyphen, not a substring), so "B" does not match "C10" or "HB".

## `hasDiscipline` (type: `boolean`):

When on, returns only licenses carrying a discipline case (DBCaseNo / DiscpCaseRegion). ~1,800 rows.

## `aggregate` (type: `boolean`):

When on, returns one summary record per group with count, instead of individual license rows.

## `changes` (type: `boolean`):

When on, returns the changes between the last two daily snapshots (added / removed / updated licenses, with changeType and changedFields) instead of records.

## `groupBy` (type: `string`):

businessType -> legal-form mix; primaryStatus -> clear vs suspended; county -> geographic mix; wcCoverage -> workers' comp coverage mix; state -> mailing-state mix.

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

Cap the number of records pushed (0 = a reasonable ceiling of 200).

## Actor input object example

```json
{
  "hasDiscipline": false,
  "aggregate": false,
  "changes": false,
  "groupBy": "county",
  "maxResults": 200
}
```

# Actor output Schema

## `recordsUrl` (type: `string`):

California CSLB contractor license records - as JSON

## `datasetUrl` (type: `string`):

No description

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

// Run the Actor and wait for it to finish
const run = await client.actor("j0401/ca-cslb-contractors").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("j0401/ca-cslb-contractors").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 j0401/ca-cslb-contractors --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,j0401/ca-cslb-contractors"
        }
    }
}
```

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/tnB2OFkuqzoI467X5/builds/gjACNSaq2Dnb6jEAx/openapi.json
