How-to
How to run Virginia Contractor Directory & Leads Scraper (DPOR)
Step-by-step: the exact input, what each field does, and the rows that come back from VA DPOR.
You sell to contractors in Virginia and you want an email list for one county and one trade: every licensed roofer in Fairfax County, say. The Virginia Department of Professional and Occupational Regulation (DPOR) already gives the whole thing away. Its Board for Contractors publishes every current licence as free tab-delimited files, one per licence class, 53,779 rows across six files when we checked on 2026-10-06. What those files lack is a county column, and the trades sit as bare codes (ROC, ELE, HIC) in one space-separated field. This actor downloads the files, maps each mailing ZIP to a county, labels the trade codes and hands back only the rows you asked for.
What you’ll need
Nothing but an Apify account. The actor talks to VA DPOR directly.
No API key, no proxy and no CAPTCHA. DPOR serves its files to plain requests, and the proxy setting ships switched off. The only charge is $0.002 per contractor returned, plus Apify’s own platform usage.
Step 1: Open the actor
Open Virginia Contractor Directory & Leads Scraper (DPOR) 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 |
|---|---|---|---|
listOptionsOnly | boolean | no | If true, skip the download and return Virginia’s 95 counties and 38 independent cities plus every trade DPOR’s Board for Contractors licenses, with its code. Free, not charged. |
trade | string | no | A DPOR trade, by name or code, e.g. ‘Roofing’, ‘Electrical’, ‘HVAC’, ‘Home Improvement’, ‘ROC’. A word from the name works too: ‘roof’ finds Roofing. Leave it empty to get… |
trades | array | no | Several trades in ONE run, e.g. Roofing and Electrical. Combined with ‘Trade’ if you fill both. A contractor holding two of them is returned (and billed) once. (default []) |
county | string | no | A Virginia county or independent city, e.g. ‘Fairfax County’, ‘Richmond city’, ‘City of Fairfax’, ‘Loudoun’. Fairfax, Franklin, Richmond and Roanoke are each both a county and… |
counties | array | no | Several counties or independent cities in ONE run. Combined with ‘County’ if you fill both. (default []) |
city | string | no | The city on the licence’s mailing address, e.g. ‘Vienna’, ‘Virginia Beach’. Exact match, case-insensitive. |
cities | array | no | Several mailing cities in ONE run, each searched separately. (default []) |
zip | string | no | A 5-digit ZIP code, matched exactly against the licence’s mailing ZIP, e.g. ‘22182’. |
zips | array | no | Several ZIP codes in ONE run, each searched separately. (default []) |
licenseClasses | array | no | Which DPOR licence classes to include: A, B, C, and RETR (residential tradesman). Only those files are downloaded. Default: A, B and C. (default ['A', 'B', 'C']) |
inVirginiaOnly | boolean | no | Keep only licences with a Virginia mailing address. About 20% of DPOR’s licences have an out-of-state address; turn this off to include them on a statewide trade search. (default True) |
maxResults | integer | no | Cap on the contractors returned PER place + trade search, not per run, so adding places can never silently truncate the ones later in the list. Leave empty to return every match. |
The field first-time users trip on is county. Fairfax, Franklin, Richmond and Roanoke are each both a county and an independent city in Virginia, so a bare “Fairfax” is refused: on 2026-10-06 it returned 192 free rows listing the counties, cities and trades you can use, with a log line asking for “Fairfax County” or “Fairfax city”. Say which one you mean. Also know that county is derived from the mailing ZIP, so it is approximate; if you need an exact match, use city or zip instead, which compare against the licence’s mailing address character for character.
trade takes a name (“Roofing”), a word from one (“roof”) or DPOR’s own code (“ROC”). If you are not sure what DPOR calls a trade, switch on listOptionsOnly once; it returns every trade with its code and costs nothing.
A working input:
{
"county": "Fairfax County",
"trade": "Roofing"
}
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 118 contractors when we ran it on 2026-10-06. Almost all of the time goes on downloading the five DPOR files behind classes A, B and C (53,760 licences between them), so a run takes about as long whether you ask for one county or three: our local runs took between 7.5 and 74 seconds depending on how fast DPOR answered, before Apify’s container start-up. Adding Loudoun County and Prince William County to the same run brought it to 234 roofers. If a run returns nothing but county and trade names, one of your inputs was not recognised and the log says which; those rows are free. If DPOR does not serve a file, you get one free row with a notice saying so, never an empty dataset that reads as “no contractors here”.
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:
{
"business_name": "FSR ROOFING CONTRACTOR INC",
"individual_name": null,
"email": "fsrconstruction4u@gmail.com",
"address": "8300 OLD COURTHOUSE RD",
"city": "VIENNA",
"zip_code": "22182",
"address_state": "VA",
"county": "Fairfax County",
"county_method": "zip_single",
"license_class": "B",
"license_type": "Class B Contractor",
"specialties": [
"ROC",
"HIC"
],
"specialty_labels": [
"Roofing",
"Home Improvement"
],
"certification_date": "03/09/2004",
"expiration_date": "12/31/2027",
"license_number": "083272",
"board_occupation": "2705",
"phone": null,
"requested_county": "Fairfax County",
"requested_trade": "Roofing",
"source_url": "https://www.dpor.virginia.gov/sites/default/files/Records%20and%20Documents/Regulant%20List/2705b__crnt.txt"
}
| Field | Example value | Meaning |
|---|---|---|
business_name | FSR ROOFING CONTRACTOR INC | Business name on the licence (null for a licence held by an individual) |
individual_name | — | Individual licensee’s name, when the licence is held by a person |
email | fsrconstruction4u@gmail.com | Email on file with DPOR (null when none is on file) |
address | 8300 OLD COURTHOUSE RD | Mailing street address, including suite and PO box |
city | VIENNA | Mailing city |
zip_code | 22182 | Mailing ZIP code (ZIP+4 when DPOR has it) |
address_state | VA | State of the mailing address |
county | Fairfax County | Virginia county or independent city, derived from the ZIP (approximate, see county_method) |
People come for email. In the Fairfax roofing run, 94 of 118 rows had one, and across DPOR’s whole list it is 41,484 of 53,779 licences, about 77%. There is no phone number, on any row: DPOR does not publish one, so phone is always null and you should plan for email and mail only. The address is on every row.
Read county_method before you trust county. In the Fairfax run, 80 rows have a ZIP lying wholly inside Fairfax County (zip_single) and 38 have a ZIP that crosses a county line and was assigned to the county holding most of it (zip_majority). The mailing city tells its own story too: 20 of those 118 Fairfax County roofers have a mailing city of ALEXANDRIA, because the postal city and the jurisdiction are different things in Northern Virginia. Rows are keyed on board_occupation plus license_number, because DPOR reuses certificate numbers across licence types (53,302 distinct numbers over 53,779 rows).
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.002 per contractor returned, plus Apify’s own platform usage. The Fairfax County roofing run above is 118 rows, so $0.24. Fairfax, Loudoun and Prince William together is 234 rows, $0.47. Richmond city electrical contractors came to 41 rows, $0.08. Discovery Mode, unrecognised inputs and notice rows cost nothing, and a licence that matches two of your searches is returned and charged once.
Where the data comes from
This reads VA DPOR directly. The target is DPOR’s own regulant-list files, one tab-delimited bulk file per licence class; on 2026-10-06 every file carried a Last-Modified date of the day before, and the actor downloads them fresh on every run. Every night a canary runs this actor against that live source and checks that it still returns at least 40 Fairfax County roofers with an address, ZIP and licence number, and that at least 60% of them carry an email: what “verified” means.
The files are free at dpor.virginia.gov/RegulantLists, and if you want the whole state once, download them yourself. What makes them awkward is the shape: 57 trade codes packed into one column, no county anywhere, 10,556 licences with an out-of-state mailing address, and 22 rows where a stray tab inside the business name shifts every later column. The actor repairs those rows, drops out-of-state addresses unless you switch inVirginiaOnly off, and labels each code from the Board for Contractors regulations.
See it used
Build a Fairfax County Roofing Contractor List walks through a Northern Virginia email list for a roofing-materials supplier: 234 roofers across Fairfax, Loudoun and Prince William, 190 of them with an email.
If you already have a contractor’s name and only need to check that one licence, Virginia Contractor License Lookup is the smaller tool. For the same trade-by-county list in Arkansas, with phone numbers, use Arkansas Contractor Directory & Leads Scraper.
Last updated 2026-10-06