Contractor License Scraper avatar

Contractor License Scraper

Pricing

from $0.50 / 1,000 results

Go to Apify Store
Contractor License Scraper

Contractor License Scraper

Scrapes HVAC, plumbing, electrical, and general contractor license data from state licensing boards.

Pricing

from $0.50 / 1,000 results

Rating

0.0

(0)

Developer

Ledgerfield Data

Ledgerfield Data

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Contractor License Scraper turns 26 separate state government license lookups — normally a slow, manual, one-state-at-a-time chore — into a single structured dataset of every actively licensed General Contractor, Electrician, Plumber, and HVAC contractor across Alabama, Arizona, Colorado, Delaware, Iowa, Kentucky, Louisiana, Massachusetts, Maryland, Maine, Minnesota, Missouri, North Carolina, North Dakota, Nebraska, Nevada, New York (NYC), Ohio, Oregon, South Dakota, Tennessee, Texas, Virginia, Wisconsin, West Virginia, and Wyoming. Every record comes straight from a state's own public license-lookup site or open-data portal (no login, no paywall) — this Actor just automates the lookup, page by page, including three states that only render their data through a live browser. Run it on the Apify platform to get scheduled refreshes, instant API/webhook access to results, automatic proxy rotation, and full run monitoring — no server or browser to maintain yourself. Just 7 of the 26 states already add up to over 250,000 individual license records — see the real per-state counts below.

This is an independent, unofficial tool. It is not affiliated with, endorsed by, or operated on behalf of any state government, agency, or board named in this README — it only reads pages those agencies already publish for free, public lookup.

Why use Contractor License Scraper?

Turn newly issued licenses into a live deal-sourcing feed

A state license board is often the first public trace that a new contracting business exists — before it has a website, before it appears in any business directory, before a competitor even notices. Schedule this Actor to run weekly or monthly and diff each pull against the last one, and you get a rolling feed of brand-new market entrants and freshly renewed operators: an early-mover signal most sourcing teams currently pick up by accident (a referral, a permit filing) instead of systematically.

State license boards are also the only reliably up-to-date public registry of every actively licensed contractor in a state — most of these businesses are small, local, and otherwise invisible to standard business databases. Put together, that makes this data useful for:

  • PE roll-up sponsors & M&A advisors sourcing acquisition targets in fragmented, high-margin local-service verticals (HVAC, electrical, plumbing, roofing/general contracting) — build a state-by-state target list ranked by license tenure, trade mix, or expiration (a proxy for renewal/attrition risk), and refresh it on a schedule to catch new entrants as they appear.
  • Franchise recruiters identifying independent operators who might convert to a franchise banner — including ones too new or small to show up in a paid business database yet.
  • Distributors & suppliers (equipment, materials, insurance) building a prospect list of every licensed contractor in their territory, updated as new licenses are issued.
  • Insurers & underwriters verifying a business actually holds an active license before binding a policy or approving a claim.
  • Home-services marketplaces & lead-gen platforms vetting whether a contractor signing up is genuinely licensed in their state before listing them.
  • Market researchers sizing the number of active operators, license churn, or trade mix by state or county.

The scale, in real numbers

These aren't estimates — they're actual counts pulled from each state's own system: Oregon 102,054 (55,955 general/specialty contractor registrations + 46,099 electrical/plumbing licenses, two separate boards) · Maine 69,988 (52,501 electricians + 17,487 plumbers) · West Virginia 46,414 (34,776 electricians + 6,127 HVAC technicians + 5,511 plumbers) · Iowa 18,307 (general contractor registrations alone, before its separate electrical board) · North Dakota 8,865 (plumbing board alone, before its separate electrical and GC-registration boards) · South Dakota 2,818 · Wyoming 1,864. That's already over 250,000 records across just 7 of the 26 states — and it doesn't include the larger bulk-file states (Texas, Minnesota, Virginia, Alabama) or the several states with their own dedicated Socrata/open-data APIs (Colorado, New York).

Why not just check each state site yourself?

Because it doesn't scale past one state. Twenty-six boards means twenty-six different search forms, column layouts, and pagination styles — some run on ASP.NET WebForms from the 2000s, some on Salesforce Lightning, some publish clean open-data APIs, and a few only expose their roster as a static PDF. Three of them (Massachusetts, Missouri, Wisconsin) only render their data through a JavaScript-heavy portal that a plain HTTP request can't read at all, so a simple "view page source" approach silently returns nothing. Building and maintaining that yourself — across 26 government systems that each redesign on their own schedule — is realistically a multi-week engineering project, then an ongoing maintenance burden. This Actor already did that work and gets fixed centrally when a state changes something; you get one consistent schema across all of them instead of the upkeep.

How to use Contractor License Scraper

  1. Click Try for free (or Run) on this Actor's page.
  2. In the Input tab, pick which state(s) to pull from the states list.
  3. Optionally narrow the results with a tradeTypeFilter or statusFilter, and set maxItemsPerState to cap how many records to pull per state.
  4. Click Start and watch the run log — each state logs how many records it found.
  5. When the run finishes, open the Output tab to preview, or export the dataset as JSON, CSV, Excel, or HTML.

No coding is required to run it from the Console; developers can also call it via the Apify API or SDKs to integrate results into a CRM, spreadsheet, or data warehouse.

Input

All fields are optional except states. See the Input tab for the full form, or pass JSON directly:

{
"states": ["OR", "IA", "WY"],
"tradeTypeFilter": [],
"statusFilter": ["Active"],
"maxItemsPerState": 10000
}
  • states — which state boards to query (see the Data table below for the full list).
  • tradeTypeFilter — restrict to GC, ELECTRICAL, PLUMBING, and/or HVAC. Leave empty to include every trade each state's scraper supports.
  • statusFilter — restrict to specific statuses (values vary by state, e.g. Active, Expired). Leave empty for all.
  • maxItemsPerState — upper bound on records pulled per state per run (default 10000).

Output

Each result is one license record, pushed to the dataset in real time as each state finishes. Example item:

{
"state": "OR",
"licenseNumber": "211290",
"licenseeName": "ACE CONSTRUCTION & MECHANICAL INC",
"businessName": "ACE CONSTRUCTION & MECHANICAL INC",
"tradeType": "GC",
"licenseClass": "Residential General Contractor",
"status": "Active",
"city": "TUALATIN",
"county": "Washington",
"address": "18840 SW BOONES FERRY RD # 216",
"issueDate": "2016-07-13",
"expirationDate": "2028-07-13",
"disciplinaryFlag": false,
"sourceUrl": "https://data.oregon.gov/resource/g77e-6bhs.json",
"scrapedAt": "2026-07-11T14:00:22.377Z"
}

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel from the Output tab, or pull it programmatically via the Dataset API.

Data table

FieldDescription
stateTwo-letter state postal code
licenseNumberState-issued license/registration number (or the state's closest equivalent identifier)
licenseeNameName on the license record
businessNameBusiness/DBA name, when the state exposes one separately from the licensee name
tradeTypeGC, ELECTRICAL, PLUMBING, or HVAC
licenseClassLicense category or class (e.g. Master Electrician, Journeyman Plumber, Residential General Contractor)
statusActive, Expired, or another state-specific status label
city / countyBusiness location, where published
addressStreet address, where published
issueDate / expirationDateISO YYYY-MM-DD dates, where published
disciplinaryFlagtrue when the state's own data marks the license as suspended, conditioned, surrendered, or revoked
sourceUrlThe exact page/API endpoint the record was read from
scrapedAtUTC timestamp the record was collected

States covered: AL, AZ, CO, DE, IA, KY, LA, MA, MD, ME, MN, MO, NC, ND, NE, NV, NY, OH, OR, SD, TN, TX, VA, WI, WV, WY. Some states only license a subset of the 4 trades at the state level (e.g. Wyoming licenses electricians only; several states have no state-level GC or HVAC license at all) — see each state's entry in the Input tab for exactly which trades it covers.

How much does it cost to scrape state contractor license data?

This Actor runs on Pay Per Event pricing: $2.00 per 1,000 results, plus a small $0.02 flat fee per run — that's the whole bill. Platform compute costs are included in that price, not billed separately, so the number you see before you run it is the number you pay; three of the twenty-six states (MA, MO, WI) drive a real headless browser under the hood and cost more to run than the other twenty-three, but that's absorbed into the flat per-result price rather than passed through as a variable line item. A default run (a few thousand records per state) costs a few dollars; pulling a full state's roster (e.g. Oregon's 100,000+ combined records) costs roughly the same as a few cups of coffee. Apify Store subscribers on paid plans get this Actor's price automatically discounted — up to 75% off at the top tier. Apify's free tier is normally enough to try every state at a modest maxItemsPerState.

Tips for scraping state contractor license boards efficiently

  • Start with a small maxItemsPerState (e.g. 50) to sanity-check a state before committing to a full pull.
  • Six states (AL, AZ, MN, ME, TX, VA) publish their roster as one bulk file rather than a paginated API — maxItemsPerState still limits what's pushed to the dataset, but the Actor downloads the entire file first regardless of that cap, since there's no way to ask these sources for fewer rows. Maine alone is a ~21MB / 70,000-row combined download every time. Expect these six to take longer and use more bandwidth than a small maxItemsPerState would suggest, even when you only end up with a handful of records.
  • Run the plain-HTTP states separately from the three browser-driven states (MA, MO, WI) if you want faster turnaround — the plain-HTTP states finish in seconds, while the browser-driven states take longer per record (pricing is the same flat rate either way, this only affects run time).
  • Use tradeTypeFilter to pull just the trade you care about (e.g. ["ELECTRICAL"]) instead of every trade a state's scraper supports.
  • Use statusFilter: [] (empty) to pull every status the state publishes, not just Active.
  • Schedule recurring runs (daily/weekly) via Apify Scheduler to track new licenses and renewals over time — pair with a dedupe step on licenseNumber if you want a rolling incremental feed.

FAQ

Is this legal? This Actor only reads pages state agencies already publish for free, public lookup — the same pages a person could browse and read by hand. It does not create accounts, submit forms with personal data, or bypass any login, paywall, or CAPTCHA. You're responsible for using the output in line with each state's terms of use and applicable law.

Why do some states have fewer fields than others? Each state publishes a different amount of detail — some list a full street address, others only a county; some expose separate business and licensee names, others only one. The Actor never invents a value; a missing field is null.

Why does disciplinaryFlag say false for most states? Only a few states expose a disciplinary/enforcement-action field on their public license-lookup pages. It's kept in the schema for every state so a future update can populate it wherever a state adds one.

A state stopped returning data / a site changed. State sites occasionally redesign or move. Please open an issue on this Actor's Issues tab with the state code and what you're seeing, and it'll get investigated.

Can you add another state, or build a custom feed for my exact use case? Yes — reach out via the Issues tab or Apify's contact options to discuss a custom build (additional states, extra fields, dedupe/enrichment, or delivery straight into a CRM).