DEV Community

Loomwise
Loomwise

Posted on Edited on

Oregon Contractor Insurance Renewal Leads: 4,600 Liability Policies Expiring This Winter (CCB Open Data + Python)

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))
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Reading the results

  • License types. RGC is a residential general contractor, RSC a residential specialty contractor (roofers, painters, flooring), and CGC1/CGC2 and CSC1/CSC2 are 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_company before you write copy.
  • The date is text. ins_exp_date comes back as MM/DD/YYYY text, so ordinary date comparisons don't work. That's why the script matches on the month and year with like.

Turning it into a renewal calendar

  1. Run it on the 1st of each month for the month after next (in December, pull February).
  2. Sort by ins_exp_date and contact each business 30 to 45 days before its date.
  3. Keep license_number as your key. It's stable, and https://search.ccb.state.or.us/search/ verifies any license.
  4. 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:

Top comments (0)