← back to Rentv Licensed Targets
specs/contractors.md
16 lines
# Contractors / Builders — access spec [discovery: COMPLETE + VERIFIED 2026-07-31]
## 1. CA CSLB ✅ BEST — direct no-auth master CSV (feed-first, $0, one GET)
- Endpoint (PROVEN 200 text/csv, no cookie/captcha): `https://www2.cslb.ca.gov/OnlineServices/DataPortal/DownLoadFile.ashx?fName=MasterLicenseData&type=C` (`type=E` = Excel). Skip the ASP.NET portal postback — hit the .ashx directly. Refreshed ~weekly ("as of 7/28/2026").
- 52 cols (header verified): LicenseNo, BusinessName, FullBusinessName, MailingAddress, **City, State, County, ZIPCode**, BusinessPhone, BusinessType, IssueDate, ExpirationDate, **PrimaryStatus**, SecondaryStatus, **Classifications(s)**, WC fields… (no email/website).
- Commercial filter: `Classifications(s)` contains B (General Building) / A (Engineering) / relevant C-codes (C-8,C-10,C-20,C-36,C-39,…). Geo: `County IN (Los Angeles, Orange, Riverside, San Bernardino, San Diego, Ventura)` (+Santa Barbara/Kern/Imperial for full 300mi). Status: PrimaryStatus CLEAR/Active.
- ~290k statewide → ~120–160k SoCal commercial-relevant before status filter. **One curl → COPY into staging → filter in SQL. $0.**
## 2. AZ ROC ✅ Commercial CSV (Steve's link — VERIFIED 47,235 records via browser)
- File: `https://roc.az.gov/sites/default/files/ROC_Posting-List_Commercial_<YYYY-MM-DD>.csv` off `roc.az.gov/posting-list`. Whole roc.az.gov is Cloudflare-walled to curl (403) → **fetch via a real browser (Playwright cf_clearance cookie)**; verified 200 / **47,235 "Current Active Commercial Contractor Licenses"**.
- Cols: #, License No, Business Name, Doing Business As, Class, Class Detail, Class Type, Address, City, State, Zip, Qualifying Party, Issued Date, Expiration Date, Status. (No county/phone/website → derive county from ZIP 85xxx=Maricopa.)
- Already commercial-only (dedicated file) → just geo-filter to Maricopa/Scottsdale. Sibling files: All / Dual / Residential / Pending-Applications / New-Licenses / Disciplinary-Actions (same dir, daily).
- Alt scriptable path (no browser): `POST azroc.my.site.com/AZRoc/s/sfsites/aura` action `ARCP_ContractorSearch.getRecords` (search-driven, paced). Bulk ToS-clean fallback: ROC Public Records Request.
## Land in `rentv_licensed_targets` role='Contractor' source cslb / az_roc. Both are effectively feed-first ($0); AZ just needs the browser hop for the WAF.