If you sell general liability insurance or surety bonds to contractors, the best moment to call is a few weeks before their policy renews. In most states you have to guess when that is. Oregon tells you.
The Oregon Construction Contractors Board (CCB) publishes every active license on data.oregon.gov, and each row includes the contractor's current insurance carrier, coverage amount and policy expiration date, plus the surety bond company and bond amount. No API key, no login.
When I ran this on Oct 24, 2026, 4,610 contractor businesses (LLCs, corporations and partnerships only) had a liability policy expiring in November or December 2026: 2,106 in November and 2,504 in December.
The script
import requests, re
from collections import Counter
from datetime import date
ENTITY = re.compile(r"\b(LLC|L\.L\.C|INC|CORP|CORPORATION|CO|COMPANY|LLP|LP|LTD)\b", re.I)
def oregon_policies_expiring(months):
# ins_exp_date is text like '11/30/2026', so match on month/year
where = " OR ".join(f"ins_exp_date like '{m:02d}/%/{y}'" for y, m in months)
rows = requests.get("https://data.oregon.gov/resource/g77e-6bhs.json", params={
"$select": "license_number,full_name,license_type,city,county_name,ins_company,ins_amount,ins_exp_date",
"$where": where, "$limit": 50000}, timeout=120).json()
return [r for r in rows if ENTITY.search(r.get("full_name", ""))] # businesses only
rows = oregon_policies_expiring([(2026, 11), (2026, 12)])
print(len(rows), "Oregon contractor businesses with liability policies expiring Nov-Dec 2026")
print("Top carriers:", Counter(r.get("ins_company") for r in rows).most_common(5))
print("License types:", Counter(r.get("license_type") for r in rows).most_common(5))
print("Counties:", Counter(r.get("county_name") for r in rows).most_common(5))
Output on Oct 24, 2026:
4610 Oregon contractor businesses with liability policies expiring Nov-Dec 2026
Top carriers: NEXT INSURANCE US COMPANY 302, CBIC 272, OHIO SECURITY INSURANCE COMPANY 206, SCOTTSDALE INSURANCE CO 176, CONTINENTAL CASUALTY COMPANY 127
License types: RGC 2718, CGC2 596, RSC 575, CGC1 276, CSC2 248
Counties: Out of State 876, Multnomah 550, Clackamas 481, Washington 469, Marion 413
Reading the results
-
License types.
RGCis a residential general contractor,RSCa residential specialty contractor (roofers, painters, flooring), andCGC1/CGC2andCSC1/CSC2are commercial general and specialty contractors at two size levels. Coverage minimums differ by type, so segment your pitch. - "Out of State" is a real segment. 876 of the expiring policies belong to contractors based outside Oregon (mostly Washington and Idaho) who still hold an Oregon license. They often carry a policy from their home state and are worth a separate campaign.
-
Carrier tells you the angle. A contractor on a monoline digital carrier and one with a large regional carrier usually want different conversations. Group by
ins_companybefore you write copy. -
The date is text.
ins_exp_datecomes back asMM/DD/YYYYtext, so ordinary date comparisons don't work. That's why the script matches on the month and year withlike.
Turning it into a renewal calendar
- Run it on the 1st of each month for the month after next (in December, pull February).
- Sort by
ins_exp_dateand contact each business 30 to 45 days before its date. - Keep
license_numberas your key. It's stable, andhttps://search.ccb.state.or.us/search/verifies any license. - Respect the do-not-call rules for business numbers in your state, and stick to the businesses. The script drops sole proprietors on purpose.
The same dataset also has orig_regis_date, so you can flip this around and find brand-new contractors who just bought their first policy. I covered that in an earlier post in this series.
Optional: if you'd rather not maintain the script, I publish this as a hosted, scheduled tool: Oregon CCB Contractor License Scraper (paid per result, with insurance and bond fields included). Disclosure: it's my tool. The code above does the same job for free.
Free sample data
See the fields before you run anything:
- Oregon contractor leads list: free sample CSV
- Lead lists for leads for insurance agents
- All public-data lead lists <!-- /loomwise-data-links -->
Top comments (0)