Use case
Build a Multnomah County Residential Contractor List
Pull every CCB-licensed residential general contractor in Multnomah County with bond, insurance and expiration attached - one run instead of paging CCB search.
Say you are a surety and commercial-lines producer in Portland, and contractors are the book you want to grow. Your problem is timing rather than names: a contractor shops their bond and their liability cover when a renewal is in front of them, and ignores you completely the other eleven months. So the list you actually want is not “residential GCs in Multnomah County” — it is residential GCs in Multnomah County, with the bond amount they carry, the carrier who wrote it, and the date the licence next comes up, sorted so you can work forward from next month.
Oregon is the state where you can build that in one run, because the CCB publishes the bond and insurance details as part of the licence record.
The manual way, and what it costs
The CCB’s own search at search.ccb.state.or.us is the tool for a single contractor: type a licence number or a business name, get the full record including the surety and the carrier. If you are checking one account before quoting it, use that — it is authoritative, free and instant, and nothing here beats it.
It is a lookup tool, though, not a list tool. It answers questions about contractors you can already name, which is the opposite of prospecting. The same data is also published as an open dataset on data.oregon.gov, and you can filter and export that yourself — but you are then handling the state’s raw column names, deciding which of the endorsement codes count as “residential general”, and repeating the whole exercise every time you want a fresh cut. Do it once a quarter and it is an hour you will not get back; do it monthly, which is what renewal-driven outreach actually needs, and it is a standing chore.
The faster way
Oregon Contractor Directory & Leads Scraper (CCB) does the same search once and hands back every row at once.
{
"county": "Multnomah",
"licenseType": "Residential General Contractor",
"maxResults": 200
}
county is matched server-side against the CCB’s own county field, so only Multnomah rows ever
cross the wire — this is not a whole-state download filtered afterwards. licenseType is a
substring match against the endorsement description, which is more flexible than it looks and
worth using deliberately: "Residential General Contractor" pins you to that one endorsement,
"Residential" widens it to specialty contractors as well, and "Contractor" matches nearly
everything and is a waste of a filter. maxResults: 200 is a look-first cap on a county with
thousands of active records; raise it once the rows are the shape you expected. (The sample row
below comes from an unfiltered run, which is why it shows a Residential Specialty endorsement —
with the filter above, every row would read Residential General Contractor.)
What comes back
{
"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/"
}
| Field | Example value | Meaning |
|---|---|---|
state | OR | Always ‘OR’ for this actor |
county | Multnomah | Oregon county of the contractor’s business address |
license_number | 100260 | CCB license number |
license_type | RSC | CCB license type code (e.g. RSC, RGC, CGC, LBPR) |
license_endorsement | Residential Specialty Contractor | Human-readable CCB endorsement description (e.g. Residential General Contractor, Commercial Specialty Contractor) |
business_name | THE FOXGLOVED PAINTERS & DESIGNERS INC | Licensed business or entity name |
Four fields do the work for a producer, and they are four fields most contractor directories simply
do not have. expiration_date sets the calendar. bond_company and insurance_company tell you
who you are competing against on each account — a column of carrier names is a competitive map of
your own market, and it is free. bond_amount and insurance_amount size the account and flag the
outliers: a firm carrying the smallest bond in the county is either very small or has never been
asked the right questions. rmi_name is the Responsible Managing Individual — the person the CCB
holds accountable for the licence, and usually the person worth asking for by name rather than
“whoever handles insurance”. phone and address mean the row is directly workable without an
enrichment step.
What you’d do with it
Export to CSV, sort ascending on expiration_date, and slice off the rows expiring in the next
sixty to ninety days — that is your working list, and everything after it is a future month’s
list. Add a column that flags any row where bond_company or insurance_company is blank, because
a missing filing is either a data gap or a coverage gap and both are a reason to call. Key the
import on license_number, re-run monthly, and the diff gives you two more lists for free: newly
licensed contractors who have never bought from anyone, and firms that changed carrier since last
month.
Worth knowing
This is the active-licence dataset, and it has no status field at all. Every row you get is a licence the CCB publishes as active — which also means there is nothing in the record to tell you that a licence lapsed yesterday. The export lags the registry by a few days, so a recently expired or cancelled licence can still be sitting in your file. Before you bind anything on the strength of a row, re-check that one licence at the source.
Bond, insurance and RMI are null when nothing is on file. These come straight from CCB. A blank
bond_company means the CCB has no filing recorded, not that the actor failed to fetch it — a
distinction that matters if you are planning to treat blanks as leads.
County means business address. A contractor registered at a Clackamas County office who works Portland every day is a Clackamas row. County-scoped lists are a good approximation of a territory and never a precise one.
The endorsement filter is a substring, so it will over-match if you let it. Broad terms catch
endorsements you did not intend. Check the license_endorsement values in your first 200 rows
before you scale the run up.
Run it yourself: How to run Oregon Contractor Directory & Leads Scraper (CCB) walks the whole thing step by step.
Before you bind: Check an Oregon Contractor’s Bond and Insurance re-verifies a single account at the source, which is the step this list does not replace — Oregon Contractor License Lookup & Verify (CCB) is the actor behind it.
Last updated 2026-07-22