# Oregon Contractor Directory & Leads Scraper (CCB) (`fried_calamaries/oregon-contractor-directory-leads-scraper`) Actor

Pull every CCB-licensed contractor in any Oregon county — business name, license type, RMI, bond, insurance, address, and phone — direct from the official state open-data API.

- **URL**: https://apify.com/fried\_calamaries/oregon-contractor-directory-leads-scraper.md
- **Developed by:** [ByteMe](https://apify.com/fried_calamaries) (community)
- **Categories:** Lead generation
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.002 / contractor 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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## Oregon Contractor Directory & Leads Scraper (CCB)

### Pain points

- The CCB online portal lets you look up one contractor at a time — there is no way to export an entire county's roster as a spreadsheet.
- Building a county-scoped contractor prospect list from the CCB website requires hundreds of individual searches and hours of manual copy-paste.
- Sales teams, GCs, and insurance agents need structured, county-filtered contact data — not a slow per-lookup search form.

### What we solve

- Pull every CCB-licensed contractor in any Oregon county in a single run — no per-record search, no manual export.
- Returns license number, type code, endorsement description, business name, RMI, address, phone, bond, and insurance, structured and ready to import.
- Filter by endorsement keyword (e.g. 'Residential General Contractor', 'Electrical', 'Plumbing') to narrow the list before it lands in your CRM.

### Summary

Browse the complete roster of Oregon Construction Contractors Board (CCB) licensed contractors in any county — just supply a county name and get back every active licensee on record: CCB license number, type code, endorsement description (e.g. Residential General Contractor, Commercial Specialty Contractor), business name, Responsible Managing Individual (RMI), street address, phone, bond company and amount, and insurance company and amount. Data comes straight from the official Oregon open-data Socrata API (data.oregon.gov, dataset g77e-6bhs) — authoritative, up-to-date, no scraping fees beyond the flat per-record PPE charge. Optional endorsement-type filter narrows results to a specific trade before they hit your dataset. Ideal for building targeted contractor prospect lists, compliance coverage maps, and territory-scoped outreach campaigns.

### Who it's for

- Sales and BD teams building county-scoped contractor prospect lists for tools, materials, or subcontracting services
- Insurance and bonding agents prospecting for contractor accounts in an Oregon county territory
- General contractors and developers building subcontractor shortlists by county and trade endorsement
- Compliance teams and market researchers mapping licensed contractor coverage across Oregon counties

### 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
{
  "county": "Multnomah",
  "licenseType": "Residential General Contractor",
  "maxResults": 200
}
````

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

### What you get

One row per record:

| Field | Description |
|---|---|
| `state` | Always 'OR' for this actor |
| `county` | Oregon county of the contractor's business address |
| `license_number` | CCB license number |
| `license_type` | CCB license type code (e.g. RSC, RGC, CGC, LBPR) |
| `license_endorsement` | Human-readable CCB endorsement description (e.g. Residential General Contractor, Commercial Specialty Contractor) |
| `business_name` | Licensed business or entity name |
| `rmi_name` | Responsible Managing Individual (RMI) name (when on file) |
| `address` | Business street address |
| `city` | Business city |
| `zip_code` | Business ZIP code |
| `phone` | Business phone number (when published) |
| `issue_date` | Original CCB registration date (MM/DD/YYYY) |
| `expiration_date` | License expiration date (MM/DD/YYYY) |
| `bond_amount` | Surety bond amount in USD (when on file) |
| `bond_company` | Surety bond provider name (when on file) |
| `insurance_amount` | Liability insurance coverage amount in USD (when on file) |
| `insurance_company` | Liability insurance provider name (when on file) |
| `source_url` | Link to the Oregon CCB contractor search |

Sample:

```json
{
  "state": "OR",
  "county": "Multnomah",
  "license_number": "100260",
  "license_type": "RSC",
  "license_endorsement": "Residential Specialty Contractor",
  "business_name": "THE FOXGLOVED PAINTERS & DESIGNERS INC",
  "rmi_name": "CICELY W KEIRNAN",
  "address": "8737 NE THOMPSON ST",
  "city": "PORTLAND",
  "zip_code": "97220",
  "phone": "5032552327",
  "issue_date": "06/30/1994",
  "expiration_date": "05/14/2027",
  "bond_amount": "20000",
  "bond_company": "WESTERN SURETY COMPANY",
  "insurance_amount": "1000000",
  "insurance_company": "TWIN CITY FIRE INS COMPANY",
  "source_url": "https://search.ccb.state.or.us/search/"
}
```

### Inputs

| Field | Required | Type | Default | Description |
|---|---|---|---|---|
| `county` | yes | string | `"Multnomah"` | Oregon county name to retrieve contractors for (e.g. 'Multnomah', 'Lane', 'Washington'). Required. |
| `licenseType` | no | string | — | Optional partial match against the CCB endorsement description (e.g. 'Residential General Contractor', 'Electrical', 'Plumbing'). Leave blank for all license types. |
| `maxResults` | no | integer | `500` | Cap on the number of records to return in a single run. Defaults to 500. |

### Pricing (Pay Per Event)

You pay per result (`dataset-item`) — **no charge for empty runs**. Example: **500 contractor records** at *$0.002/result* ≈ **$1.00**.

Illustrative — the final per-record price is set at publish time. Apify platform usage (compute) is billed separately per your plan.

### Use cases

- Outbound lead generation — pull every active Residential General Contractor or specialty sub in Multnomah or Washington County, enrich with phone and address, and load into your CRM for cold outreach.
- Territory mapping — build a full picture of licensed trade coverage in a county for market-entry research or competitive analysis.
- Subcontractor discovery — find every licensed contractor with a specific endorsement (plumbing, electrical, roofing) in a county before bidding a project.
- Insurance and bonding prospecting — export the county roster with bond and insurance details to identify contractors approaching renewal or with coverage gaps.

### Why this actor

- Direct from the official CCB open-data API (data.oregon.gov) — authoritative state data, not a third-party copy.
- County-scoped in one run — pull the full Multnomah, Lane, or Washington County roster without per-record searching.
- Bond and insurance fields included — CCB data includes surety bond company and amount plus liability insurance company and amount for every contractor that has filed them.
- Endorsement-type filter narrows results before they hit your dataset — residential GC only, electrical only, or the full mix.
- Pay per record; no results, no charge.

### Limitations & updates

Covers Oregon CCB-licensed contractors only (the 'CCB Active Licenses' dataset). The dataset reflects active licenses as published; recently expired or cancelled licenses may lag by a few days. Bond, insurance, and RMI fields are null when not on file with CCB. County filter matches the business address county; licensees whose mailing address differs from their business address may not appear in the expected county. The endorsement-type filter is a substring match — broad terms like 'Contractor' match many endorsements.

### FAQ

**Where does the data come from?**

The official Oregon Construction Contractors Board (CCB) open-data registry, published on data.oregon.gov (Socrata, dataset g77e-6bhs — 'CCB Active Licenses'). Public, authoritative, and refreshed regularly.

**What does the licenseType filter match?**

It does a case-insensitive substring match against the CCB endorsement description field (e.g. 'Residential General Contractor', 'Commercial Specialty Contractor', 'Lead Based Paint Renovation Contractor'). Pass a partial string like 'General' or 'Electrical' to catch multiple related endorsements.

**How many records does a typical county run return?**

Multnomah County alone has over 6,500 active CCB records; Lane County has around 2,500; Washington County around 3,000. Smaller rural counties may have a few hundred. The actor pages through all results automatically.

**What are the license type codes?**

Common codes include RGC (Residential General Contractor), RSC (Residential Specialty Contractor), CGC (Commercial General Contractor), CSC (Commercial Specialty Contractor), LBPR (Lead-Based Paint Renovation Contractor), and others. The license\_endorsement field gives the full human-readable description for each.

**How do I find the right county name?**

Use title-case Oregon county names: Multnomah, Lane, Washington, Clackamas, Marion, Jackson, Deschutes, etc. The actor normalizes case, so 'multnomah' and 'MULTNOMAH' both work.

**How am I charged?**

Pay per record returned — one PPE event per dataset item. Runs with no results incur no charge.

**Is this personal data?**

It's public professional-license data (business and license records as CCB publishes them); no personal/PII enrichment is added beyond what the state publishes.

**How current is the data?**

The CCB open-data export is refreshed regularly on data.oregon.gov; records reflect the most recently published snapshot. Expect up to a few days of lag for brand-new registrations.

### Which actor to choose

Part of the contractor-data suite — pick the one that fits your goal:

- **Oregon Contractor License Lookup & Verify (CCB)** — You have a specific CCB license number or business name and want to verify one contractor's status, bond, insurance, and RMI.
- **Washington Contractor Directory & Leads Scraper (L\&I)** — You need the same county-level directory for Washington State contractors (L\&I).
- **Texas Contractor Directory & Leads Scraper (TDLR)** — You need a county-scoped roster of Texas TDLR-licensed contractors.
- **Multi-State Contractor & Trade License Lookup** — You need the same contractor verified across OR, WA, TX, CA, and other states in one run.

# Actor input Schema

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

Oregon county name to retrieve contractors for (e.g. 'Multnomah', 'Lane', 'Washington'). Required.

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

Optional partial match against the CCB endorsement description (e.g. 'Residential General Contractor', 'Electrical', 'Plumbing'). Leave blank for all license types.

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

Cap on the number of records to return in a single run. Defaults to 500.

## Actor input object example

```json
{
  "county": "Multnomah",
  "maxResults": 500
}
```

# Actor output Schema

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

Licensed contractors in the county, one row per CCB registration.

# 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 = {
    "county": "Multnomah"
};

// Run the Actor and wait for it to finish
const run = await client.actor("fried_calamaries/oregon-contractor-directory-leads-scraper").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 = { "county": "Multnomah" }

# Run the Actor and wait for it to finish
run = client.actor("fried_calamaries/oregon-contractor-directory-leads-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "county": "Multnomah"
}' |
apify call fried_calamaries/oregon-contractor-directory-leads-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=fried_calamaries/oregon-contractor-directory-leads-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Oregon Contractor Directory & Leads Scraper (CCB)",
        "description": "Pull every CCB-licensed contractor in any Oregon county — business name, license type, RMI, bond, insurance, address, and phone — direct from the official state open-data API.",
        "version": "0.0",
        "x-build-id": "Ay3Y8e1XjH0EaQRvH"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/fried_calamaries~oregon-contractor-directory-leads-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-fried_calamaries-oregon-contractor-directory-leads-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/fried_calamaries~oregon-contractor-directory-leads-scraper/runs": {
            "post": {
                "operationId": "runs-sync-fried_calamaries-oregon-contractor-directory-leads-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/fried_calamaries~oregon-contractor-directory-leads-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-fried_calamaries-oregon-contractor-directory-leads-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "county"
                ],
                "properties": {
                    "county": {
                        "title": "County",
                        "type": "string",
                        "description": "Oregon county name to retrieve contractors for (e.g. 'Multnomah', 'Lane', 'Washington'). Required."
                    },
                    "licenseType": {
                        "title": "License type filter",
                        "type": "string",
                        "description": "Optional partial match against the CCB endorsement description (e.g. 'Residential General Contractor', 'Electrical', 'Plumbing'). Leave blank for all license types."
                    },
                    "maxResults": {
                        "title": "Maximum results",
                        "minimum": 1,
                        "maximum": 50000,
                        "type": "integer",
                        "description": "Cap on the number of records to return in a single run. Defaults to 500.",
                        "default": 500
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
