If you sell to trades (equipment distributors, insurance, software, staffing, training), Texas is the biggest market in the country, and its licensing agency publishes the whole register for free. The Texas Department of Licensing and Regulation (TDLR) license file on data.texas.gov is updated regularly and needs no API key.
When I ran this on Oct 23, 2026 it returned 9,249 A/C contractor businesses and 8,841 electrical contractor businesses (after dropping individual licensees). Harris County leads with 1,387 A/C contractors, then Dallas (876), Tarrant (601) and Bexar (523).
The script
import re, requests
from collections import Counter
ENTITY = re.compile(r"\b(LLC|L\.L\.C|INC|CORP|CORPORATION|CO|COMPANY|LP|LTD|PLLC)\b\.?", re.I)
def texas_contractors(license_type="A/C Contractor", county=None):
where = f"license_type = '{license_type}'"
if county:
where += f" AND business_county = '{county.upper()}'"
rows = requests.get("https://data.texas.gov/resource/7358-krk7.json", params={
"$select": "license_type,license_number,business_name,business_county,business_city_state_zip,license_expiration_date_mmddccyy",
"$where": where, "$order": "license_number DESC", "$limit": 50000}, timeout=120).json()
return [r for r in rows if ENTITY.search(r.get("business_name", ""))]
types = requests.get("https://data.texas.gov/resource/7358-krk7.json", params={
"$select": "license_type, count(*) AS n", "$group": "license_type", "$order": "n DESC", "$limit": 60}, timeout=120).json()
print([(t["license_type"], t["n"]) for t in types if "Contractor" in t["license_type"]])
ac = texas_contractors("A/C Contractor")
el = texas_contractors("Electrical Contractor")
print(len(ac), "A/C contractor businesses;", len(el), "electrical contractor businesses")
print("Top A/C counties:", Counter(r.get("business_county", "").title() for r in ac).most_common(5))
print(ac[:2])
Swap the license type for Appliance Installation Contractor, Electrical Sign Contractor or Elevator Contractor, or pass county="Travis" to narrow down.
Things that will trip you up
-
Individuals and businesses share one file. Technicians and journeymen are listed under their own names. Filtering
business_namefor LLC, Inc and similar markers keeps only companies. That's better for privacy, and companies are the buyers anyway. -
Expiration dates are
MM/DD/YYYYtext. Parse them in Python before sorting. A license expiring within 60 days is a renewal trigger, which is useful timing for insurance agents and CE course sellers. -
License numbers are strings, so
$ordersorts them as text. Higher numbers are generally newer licenses, but sort numerically in Python if it matters. - "Out of State" is a real county value. Those are contractors based elsewhere who are licensed to work in Texas.
Turning it into a lead list
Export to CSV with csv.DictWriter, de-duplicate on license_number, and re-run monthly to catch new numbers. Pair it with a building permits feed to see which of these contractors are actually pulling jobs.
Optional: if you'd rather not maintain the script, I publish this as a hosted, scheduled tool: Texas Contractor Licenses (paid per result). I also publish Texas New Business Leads. Disclosure: they're my tools. The code above does the same job for free.
Free sample data
See the fields before you run anything:
- Texas HVAC and electrical contractor leads: free sample CSV
- All public-data lead lists <!-- /loomwise-data-links -->
Top comments (0)