How-to
How to run Delaware Contractor License Lookup & List Scraper (DOR + DPR)
Step-by-step: the exact input, what each field does, and the rows that come back from Delaware's Division of Revenue and Division of Professional Regulation.
You want a list of the contractors licensed to work in Delaware, or in one Delaware town, and you have found that the state keeps two lists. The Division of Revenue (DOR) licenses contracting businesses; the Division of Professional Regulation (DPR) licenses individual electricians, plumbers and HVACR technicians. Both are free on data.delaware.gov, but the business list mixes contractors in with every other kind of Delaware business, repeats a firm once per trade name, and the DPR list covers 38 professions and every status ever recorded. This actor reads both, keeps only the contractor and trade licences, and returns one row per licence: 20,420 of them statewide when we ran it on 2026-10-07.
What you’ll need
Nothing but an Apify account. The actor talks to data.delaware.gov directly.
No API key, no proxy and no CAPTCHA. Both rosters are public-domain open data on the state’s own query API, and the proxy setting ships switched off. The only charge is $0.004 per licence returned, plus Apify’s own platform usage.
Step 1: Open the actor
Open Delaware Contractor License Lookup & List Scraper (DOR + DPR) on the Apify Store and press Try for free. The actor’s own page on this site lists its live health and pricing.
Step 2: Fill in the input
| Field | Type | Required | What it does |
|---|---|---|---|
source | string | no | Which Delaware roster to read. ‘business’ = contractor business licences from the Division of Revenue (firms, with street address). ‘trade’ = electrical, plumbing and HVACR… (default both) |
residency | string | no | Resident or non-resident contractor business licence category. Applies to business licences only; setting it leaves trade licences out. (default all) |
trade | string | no | A DPR trade: ‘electrical’, ‘plumbing’, ‘hvacr’, ‘homeowner’ (homeowner electrical permits, left out unless asked for), or an exact licence type such as ‘Master Electrician’,… |
trades | array | no | Several trades in ONE run, e.g. plumbing and hvacr. Combined with ‘Trade’ if you fill both. (default []) |
status | string | no | Trade-licence status. ‘active’ (default) keeps current licences; ‘all’ includes expired, closed and revoked ones. The business roster lists only current licences, so ‘active’… (default active) |
city | string | no | City on the licence, exact match ignoring case, e.g. ‘Dover’ or ‘Wilmington’. Partial city names do not match. |
cities | array | no | Several cities in ONE run. Combined with ‘City’ if you fill both. (default []) |
zip | string | no | ZIP on the licence, 5 digits (a ZIP+4 is accepted and matched on its first 5). |
zips | array | no | Several ZIPs in ONE run. Combined with ‘ZIP code’ if you fill both. (default []) |
name | string | no | Text the name contains (case-insensitive): the legal business name or any trade name (DBA) on business licences, or ‘LAST,FIRST’ on trade licences, e.g. ‘ELECTRIC’ or ‘SMITH’. |
names | array | no | Several name fragments in ONE run; a licence matching any of them is returned once. The run log says how many returned licences each one matched. (default []) |
maxResults | integer | no | Cap on licences returned for the whole run (a spend control). Both rosters together are about 20,400 current licences, so 100000 returns everything that matches. The run log… (default 500) |
The field that decides what you get is source. Left at both, every run returns business licences first and trade licences after them, so a Dover run mixes 670 firms with 211 individual electricians and plumbers. If you only want firms you can mail, set source to business. The second trap is that some filters belong to one roster only: setting trade to hvacr leaves the business roster out entirely, and setting residency leaves the trade roster out. The actor drops the roster that cannot apply the filter rather than ignoring the filter, so you never get 13,215 unfiltered firms because you asked for HVACR.
city is an exact match on the city printed on the licence. “Dover” matches DOVER; “Dov” matches nothing. maxResults is one cap for the whole run, not per roster, and the default of 500 is a spend control: raise it to 100000 for a full export.
A working input:
{
"city": "Dover",
"maxResults": 1000
}
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.
The input above returned 881 licences in 2.0 seconds of scraping when we ran it locally on 2026-10-07: 670 business licences and 211 active trade licences, and the log prints each roster’s count before it returns anything (“business licences: 670 match; returning 670”). The whole state, with maxResults at 100000, took 7.6 seconds for 20,420 rows. If a run hits the cap, the log states how many licences matched in total, so a capped run never reads as complete. A trade or ZIP the actor does not recognise is dropped with a log line, and if none of your values is recognised you get one free row explaining it, never the whole state.
Step 4: Read the output
Each run returns a labelled table, not raw JSON:
Every row looks like this, a real row from a real run:
{
"license_number": "1989001012",
"dataset": "business_license",
"license_category": "RESIDENT CONTRACTOR",
"board": null,
"residency": "resident",
"status": null,
"business_name": "HATZEL & BUEHLER INC",
"trade_names": [],
"person_name": null,
"issue_date": null,
"valid_from": "2025-01-01",
"expiration_date": "2027-12-31",
"address": "1 RIGHTER PARKWAY, SUITE 300",
"city": "WILMINGTON",
"address_state": "DE",
"zip_code": "19803",
"state": "DE",
"source_url": "https://data.delaware.gov/resource/5zy2-grhr.json?license_number=1989001012"
}
| Field | Example value | Meaning |
|---|---|---|
license_number | 1989001012 | State licence number, one row per licence within each roster |
dataset | business_license | business_license (Division of Revenue) or trade_license (DPR) |
license_category | RESIDENT CONTRACTOR | Business category (e.g. RESIDENT CONTRACTOR) or DPR licence type (e.g. Master Electrician) |
board | — | Electrical Examiners or Plumbing/HVACR (trade licences) |
residency | resident | resident or non_resident (business licences) |
status | — | DPR status, e.g. Active or Expired (trade licences) |
business_name | HATZEL & BUEHLER INC | Legal business name |
trade_names | [] | Other ‘doing business as’ names on the same licence |
Read dataset first, because the two kinds of row carry different fields. A business licence has a street address on all 13,215 rows of the 2026-10-07 statewide run, plus residency and the current licence term. A trade licence is a person (person_name, e.g. THOMAS BROWN, Master HVACR Restricted) with a status and issue date but only a city and ZIP: address was null on all 7,205 trade rows. Neither roster has a phone number or an email, on any row, and the actor does not add one.
The two rosters are not joined. There is no shared key between a firm’s DOR licence and the DPR licence of the master electrician who works for it, and matching a firm name to a person’s name would be guesswork, so the actor does not try. trade_names folds a firm’s DBAs into a list (4,070 business licences carry at least one), which is why 13,417 source rows become 13,215 licences. And address_state is worth a look before you plan a mailing: 1,410 of the business licences are Maryland addresses and 1,399 Pennsylvania.
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 Dover run above is 881 rows, so $3.52; the business licences alone (670) would be $2.68. The full statewide export of 20,420 licences comes to $81.68. Rows explaining an outage, an unrecognised filter or an empty result are free.
Where the data comes from
This reads two public-domain datasets on data.delaware.gov: Delaware Business Licenses (Department of Finance, Division of Revenue) and Professional and Occupational Licensing (Department of State, Division of Professional Regulation), queried with SoQL on every run. Every night a canary runs this actor against that live source and checks that a Dover business-licence run still returns at least 40 licences with a name, street address, city, ZIP and category: what “verified” means.
This is an easy target, and you can skip us: both datasets have an Export button, and if you want the state once, download them. The work is in the filtering. The business set holds every kind of Delaware business licence and contractors are four of its categories; the DPR set mixes electricians with 37 other professions, and keeps expired and revoked licences next to active ones. The dataset page says it publishes daily, yet the last update when we looked was September 29, eight days earlier, so read the data as current to the state’s last refresh, not to the hour.
See it used
List Dover, Delaware Contractor and Trade Licences builds a territory list for Kent County’s county seat: 670 firms with a street address and 211 licensed tradespeople.
If you need the same kind of statewide export for Virginia, Virginia Contractor License Lookup (DPOR Bulk) reads Virginia’s regulant files, and those carry an email address on most rows.
Last updated 2026-10-07