← Guides

How-to

How to run Ohio Contractor License Lookup & Leads Scraper (OCILB)

Step-by-step: the exact input, what each field does, and the rows that come back from OH OCILB.

You need Ohio’s licensed trade contractors as data: every HVAC contractor in one county for a sales territory, or one subcontractor’s licence number and expiry before you sign them. The Ohio Construction Industry Licensing Board (OCILB) licenses five commercial trades at state level (electrical, HVAC, hydronics, plumbing and refrigeration) and gives the whole roster away as a free download. Getting it means a three-step form on the state’s eLicense site that builds a fresh file every time, and its State box defaults to Ohio, which quietly leaves out licences held by out-of-state contractors. This actor fills in that form on every run, downloads the file and returns one clean row per licence, 12,307 of them statewide when we ran it on 2026-10-07.

What you’ll need

Nothing but an Apify account. The actor talks to OH OCILB directly.

No API key, no proxy and no CAPTCHA. The roster form is marked “No Fee Required”, and the whole exchange is three plain requests. The only charge is $0.004 per licence returned, plus Apify’s own platform usage.

Step 1: Open the actor

Open Ohio Contractor License Lookup & Leads Scraper (OCILB) on the Apify Store and press Try for free. The actor’s own page on this site lists its live health and pricing.

The Ohio Contractor License Lookup & Leads Scraper (OCILB) listing on the Apify Store
The listing on the Apify Store. Pricing and the nightly health record are both public.

Step 2: Fill in the input

The input form for Ohio Contractor License Lookup & Leads Scraper (OCILB) in the Apify Console
The input form, as it appears in the Apify Console.
FieldTypeRequiredWhat it does
tradestringnoOne OCILB trade: EL (electrical), HV (HVAC), HY (hydronics), PL (plumbing), RE (refrigeration) or TA (training agency). Words work too: ‘electrical’, ‘hvac’, ‘plumbing’. Leave…
tradesarraynoSeveral trades in ONE run, e.g. EL and PL. Combined with ‘Trade’ if you fill both. (default [])
statusstringnoOCILB’s roster lists only live licences. ‘all’ returns both ACTIVE and ACTIVE IN RENEWAL (a licence inside its renewal window); pick one to narrow it. (default all)
countystringnoOhio county of the LICENCE HOLDER as OCILB records it, e.g. ‘Cuyahoga’ or ‘Franklin County’. Matches Ohio holders only. An unrecognised county is ignored with a log line.
countiesarraynoSeveral Ohio counties in ONE run. Combined with ‘County’ if you fill both. (default [])
citystringnoCompany city, exact match ignoring case and punctuation, e.g. ‘Columbus’ (does not also match ‘Columbus Grove’).
citiesarraynoSeveral company cities in ONE run. Combined with ‘City’ if you fill both. (default [])
zipstringnoCompany ZIP, 5 digits (a ZIP+4 is accepted and matched on its first 5).
zipsarraynoSeveral company ZIPs in ONE run. Combined with ‘ZIP code’ if you fill both. (default [])
namestringnoText that the licensee’s name or the company name contains (case-insensitive), e.g. ‘MECHANICAL’ or ‘SMITH’.
namesarraynoSeveral name fragments in ONE run; a licence matching any of them is returned once. The run log says how many licences each one matched. (default [])
maxResultsintegernoCap on licences returned for the whole run (a spend control). The full statewide roster is about 12,200 contractor licences, so 100000 returns everything that matches. The run… (default 500)

The field first-time users get wrong is county, because it is not the company’s county. OCILB records the county of the licence holder, the person, and the company address sits in separate columns. A name search for one Cleveland firm on 2026-10-07 returned 15 licences at one company address, and two of them belong to a licensee recorded in Geauga County. So a county search finds licences whose holder lives there; if you mean “companies based in Cleveland”, filter on city or zip, which match the company’s address.

The other is maxResults, a cap on the whole run that defaults to 500. With no filters you get 500 of the 12,307 licences, not the state; set 100000 for a full export. trade takes the two-letter code or a plain word (“hvac” works), and a value the actor does not recognise is refused: a misspelt “Cuyahga” returned one free row explaining the problem instead of every HVAC licence in Ohio.

A working input:

{
  "trade": "HV",
  "county": "Cuyahoga",
  "maxResults": 500
}

Step 3: Run it

Press Start. Rows are pushed to the dataset as they’re found, so the run log fills in as it works.

Every run downloads the whole roster first, so a county takes as long as the state: our local runs on 2026-10-07 took 3.2 to 4.4 seconds before Apify’s container start-up. The log reports “12493 rows listed, 12484 distinct licences parsed” (the gap is licences OCILB lists twice, once under a pseudo-company called ESCROW), then how many matched each filter. The input above matched 265 HVAC licences. An honest zero comes back as one free row saying the roster loaded and nothing matched, and an outage on OCILB’s side comes back as a free row saying so, never as an empty dataset.

Step 4: Read the output

Each run returns a labelled table, not raw JSON:

The output fields returned by Ohio Contractor License Lookup & Leads Scraper (OCILB)
The output view: every field the actor returns, named and typed.

Every row looks like this, a real row from a real run:

{
  "license_number": "HV.11969",
  "trade_code": "HV",
  "license_type": "HVAC Contractor",
  "status": "ACTIVE",
  "person_name": "TIMOTHY M LAVELLE",
  "business_name": "GORMAN LAVELLE CORP",
  "in_escrow": false,
  "effective_date": "04/01/2026",
  "expiration_date": "03/31/2029",
  "address": "3459 E 52nd Pl",
  "city": "Cleveland",
  "address_state": "OH",
  "zip_code": "44127-1659",
  "phone": "(216) 641-4600",
  "fax": null,
  "email": null,
  "county": "Cuyahoga",
  "licensee_state": "OH",
  "state": "OH",
  "source_url": "https://elicense4.com.ohio.gov/Lookup/GenerateRoster.aspx"
}
FieldExample valueMeaning
license_numberHV.11969OCILB licence number with its trade prefix, e.g. HV.11969 — one row per licence
license_typeHVAC ContractorElectrical, HVAC, Hydronics, Plumbing or Refrigeration Contractor
trade_codeHVEL, HV, HY, PL or RE
statusACTIVEACTIVE or ACTIVE IN RENEWAL
person_nameTIMOTHY M LAVELLEThe licensed individual (qualifying party)
business_nameGORMAN LAVELLE CORPCompany the licence is attached to
in_escrowFalseTrue when OCILB lists the licence only under ‘ESCROW’
effective_date04/01/2026Start of the current licence term

People come for the company and its phone, and the phone is the gap. Across the 12,307 licences on 2026-10-07, 12,214 had a company street address but only 8,148 (66%) had a phone, 541 a fax and 458 an email. Whatever OCILB holds is passed through, normalised to (XXX) XXX-XXXX; the actor adds no contact data of its own.

Read the row as a licence, not a company. A licence belongs to a person in one trade, so one company often appears many times: the 12,307 licences sit under 8,499 company names, and 1,898 of those companies hold more than one. That Cleveland name search returned 15 licences from 4 people, one of whom holds the same number in all five trades (EL, HV, HY, PL and RE). De-duplicate on business_name plus address if you want one row per firm. Finally, effective_date is the start of the current term, not the year the licence was first issued, and 40 licences listed as live carry an expiry date in 2025 or earlier, so read status alongside it.

Step 5: Export it

Open the Dataset tab and export to CSV, JSON or Excel, or pull the same rows from the API, which is what you want if this is going to run on a schedule.

What it costs

$0.004 per licence returned, plus Apify’s own platform usage. The Cuyahoga County HVAC run above is 265 rows, $1.06. Checking one company by name came to 15 rows, $0.06. The default cap of 500 is $2.00, and the whole statewide roster at 12,307 licences is $49.23. Rows explaining an outage, an unrecognised filter or an empty result are free.

Where the data comes from

This reads OH OCILB directly. The target is OCILB’s own roster download (eLicense GenerateRoster form, one comma-delimited file of every active licence), fetched fresh each run. Every night a canary runs this actor against that live source and checks that Cuyahoga County HVAC still returns at least 200 licences, each with a number, type, status, expiry, licensee and county, and a phone on at least 40% of them: what “verified” means.

The roster page is free and anyone can use it: tick OCILB, pick your criteria, press Continue, download the file. If you want the state once and you clear the State box first, that file is all you need. What the actor adds is the clean-up: OCILB’s file had 12,493 rows for 12,484 licences on 2026-10-07, because a licence attached to “ESCROW” or listed once without a company appears twice, and its phones arrive as “2162554298”, “614-863-0588” and “(724)962-5742” in the same column. Ohio also licenses only these five commercial trades at state level. There is no statewide general-contractor or home-builder licence, so those firms are not in this data at all.

See it used

List Cuyahoga County HVAC Contractor Licences builds a Cleveland-area HVAC territory list: 265 licences across 250 companies, with what to do about the 40% that have no phone.

For a state that publishes the whole roster with email addresses, Virginia Contractor License Lookup is the equivalent export. To check one contractor across several states in a single run, use Multi-State Contractor & Trade License Lookup.

Last updated 2026-10-07