# West Virginia Contractor License Lookup & Leads Scraper (WVCLB) (`scrapebench/west-virginia-contractor-license-lookup`) Actor

Look up any West Virginia contractor licence by number or name, or export every current WVCLB licence statewide (17,495 on 2026-10-12) with phone, mailing address, county, classifications and expiry.

- **URL**: https://apify.com/scrapebench/west-virginia-contractor-license-lookup.md
- **Developed by:** [ScrapeBench](https://apify.com/scrapebench) (community)
- **Categories:** Lead generation
- **Stats:** 4 total users, 4 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.004 / license record

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## West Virginia Contractor License Lookup & Leads Scraper (WVCLB)

### Pain points

- The WVCLB search shows 20 contractors per page and has no export, so Kanawha County alone (802 licences on 2026-10-12) is 41 pages to copy by hand.
- Its classification menu offers 17 classes, while the licences carry 63: roofing (1,224 licences), siding (897) and finished carpentry (797) are sub-classes of Specialty, which 17,377 of the 17,495 licences hold — so the form cannot list the roofers.
- Out-of-state firms are mixed in with local ones: 7,967 of the 17,495 licences (45.5%) have a mailing address outside West Virginia.

### What we solve

- Export the whole state, or the slice you need, in one run: filter by county, any of the 63 classifications (by name or a word from it), city, or West Virginia mailing addresses only, each with a batch list.
- Every row carries the board's phone, mailing street address, county, every classification on the licence and the expiry date — the fields the search shows, in a table you can sort and import.
- Verify licences in bulk: a list of WV licence numbers, company names or DBA names returns each matching licence; names are searched in both the company and the DBA field.

### Summary

West Virginia contractor licences from the WV Contractor Licensing Board (WVCLB), read live from the board's own public search. Export mode returns current licences statewide — 17,495 on 2026-10-12 — filtered by county, classification (roofing, HVAC, electrical, general building and 59 more), city or WV-only mailing addresses. Lookup mode takes licence numbers or company/DBA names. Every row has the company, DBA, phone, mailing address, county, classifications and expiry date. Pay per licence returned.

### Who it's for

- Sales teams selling materials, equipment, insurance or software to West Virginia contractors
- Lead-generation agencies building trade-specific contractor lists by county or city
- General contractors and suppliers sourcing licensed subcontractors near a job
- Compliance, insurance and lending teams checking WV licence expiry dates in bulk

### How to use

Set the input, run the actor, and collect results from the run's dataset (export to JSON/CSV/Excel, or pull via the Apify API). Example input:

```json
{
  "county": "Kanawha",
  "classification": "roofing",
  "maxResults": 500
}
```

See **Inputs** below for every available field.

### What you get

One row per record:

| Field | Description |
|---|---|
| `license_number` | WVCLB licence number, e.g. WV038157 |
| `business_name` | Licensed company (or sole proprietor) |
| `dba_name` | Doing-business-as name, when filed |
| `phone` | Business phone as the board lists it |
| `address` | Mailing street address (can be a PO box) |
| `city` | Mailing city |
| `address_state` | Mailing state (out-of-state firms hold WV licences) |
| `zip_code` | Mailing ZIP or ZIP+4 |
| `county` | The board's county: a WV county, OUT OF STATE or INTERNATIONAL |
| `classification` | Every classification on the licence, '; '-separated |
| `classifications` | The same classifications as a list |
| `expiration_date` | Licence expiry date (YYYY-MM-DD) |
| `matched_by` | license_number, business_name or dba_name (lookup); export |
| `source_url` | The WVCLB search page the row came from |

Sample:

```json
{
  "license_number": "WV042229",
  "business_name": "ACME VENTURES COMPANY LLC",
  "dba_name": "ALMOST HEAVEN CUSTOM BUILDERS",
  "phone": "(304) 539-8230",
  "address": "PO BOX 217",
  "city": "PEYTONA",
  "address_state": "WV",
  "zip_code": "25154-0217",
  "county": "BOONE",
  "classification": "GENERAL BUILDING; SPECIALTY; DEMOLITION; SEPTIC & SEWER SYSTEMS; RESIDENTIAL POOLS (ABOVE GROUND)",
  "classifications": [
    "GENERAL BUILDING",
    "SPECIALTY",
    "DEMOLITION",
    "SEPTIC & SEWER SYSTEMS",
    "RESIDENTIAL POOLS (ABOVE GROUND)"
  ],
  "expiration_date": "2027-10-29",
  "matched_by": "export",
  "status": null,
  "license_type": "Contractor License",
  "state": "WV",
  "source_url": "https://wvclboard.wv.gov/verify/"
}
```

### Inputs

| Field | Required | Type | Default | Description |
|---|---|---|---|---|
| `query` | no | string | — | A WVCLB licence number ('WV038157', or just '38157'), or part of a company or DBA name ('Almost Heaven'). Names match anywhere in the company name and in the DBA. Leave empty to run an export instead. |
| `queries` | no | array | `[]` | Several lookups in ONE run, one per line. Combined with the field above if you fill both. |
| `county` | no | string | — | A West Virginia county ('Kanawha', 'Berkeley County'), or 'Out of State' / 'International' for the board's non-WV licences. A value that is not one of these is dropped and logged. |
| `counties` | no | array | `[]` | Several counties in ONE export. |
| `classification` | no | string | — | A WVCLB classification name or a word from one: 'roofing', 'hvac', 'electrical', 'general building', 'siding'. An exact name matches only itself ('electrical' does not also take SIGN INSTALLATION (NO ELECTRICAL)). A value that matches none of the board's 63 classifications is dropped and logged. |
| `classifications` | no | array | `[]` | Several classifications in ONE export, e.g. roofing and siding. |
| `city` | no | string | — | Mailing-address city, exact match ignoring case and punctuation, e.g. 'Charleston' (which does not include South Charleston). |
| `cities` | no | array | `[]` | Several cities in ONE export. |
| `westVirginiaAddressesOnly` | no | boolean | `false` | Out-of-state contractors hold WV licences: 7,967 of 17,495 (45.5%, 2026-10-12) have a mailing address outside West Virginia. Tick to drop them. |
| `maxResults` | no | integer | `500` | EXPORT: cap on licences for the WHOLE run — your spend control (17,495 licences statewide on 2026-10-12; set 100000 to take everything that matches). LOOKUP: cap per name or number (default 50). |
| `proxyConfiguration` | no | object | `{"useApifyProxy": false}` | Not needed: the board's search answers Apify's own IPs (measured 2026-10-12). Leave it off unless a run reports that the board refused it. |

### Pricing (Pay Per Event)

You pay per result (`dataset-item`) — **no charge for empty runs**. Example: **64 Kanawha County roofing contractors** at *$0.004/result* ≈ **$0.26**.

The default export (500 licences) costs $2.00; the whole state (17,495 licences on 2026-10-12) costs $69.98 at maxResults 100000. Apify platform usage is billed separately.

### Use cases

- Territory prospecting: export every roofing and siding contractor in Kanawha, Putnam and Cabell counties with phone and mailing address for a CRM.
- Statewide list build: take all current licences once, then re-run monthly and compare licence numbers to catch new licensees.
- Subcontractor sourcing: list HVAC or plumbing contractors with a West Virginia mailing address in Berkeley County before sending bid invitations.
- Vendor compliance: run your vendors' WV licence numbers as a lookup batch and flag any that are missing or close to expiry.

### Why this actor

- Phone on 17,480 of the 17,495 licences (99.9%), and mailing street address, county and expiry on all 17,495 (measured 2026-10-12).
- Straight from the board's own public search, read live on every run — the board states the site is updated in real time with its licensure database.
- Filter by any of the 63 classifications on the licences, not just the 17 in the board's menu; a county or classification it does not recognise is dropped and logged, never silently widened to the whole state.
- Pay per licence returned; outage and bad-input notices are free.

### Limitations & updates

Current licences only: the board's search does not list expired, revoked or lapsed licences, and publishes no status, issue date, owner or qualifier name. No email: the board publishes none. Addresses are mailing addresses (3,136 of 17,495 are PO boxes), so a city filter finds where the contractor's mail goes, not where they work. 15 of the 17,495 licences have no phone on file. The board's search returns at most 1,000 rows per request, so the whole state takes about 4 minutes (17,495 licences fetched in 216 s on Apify, 2026-10-12).

### FAQ

**Where does the data come from?**

From the West Virginia Contractor Licensing Board's public contractor search (wvclboard.wv.gov/verify/), queried live on every run. Nothing is cached: each row is what the board's search returned at run time.

**How many licences are there?**

17,495 on 2026-10-12. Largest counties: Kanawha 802, Berkeley 654, Monongalia 648, Harrison 446, Raleigh 445, Cabell 442. 7,832 carry the board's OUT OF STATE county. Most common classifications after Specialty: General Building 5,388, Residential 2,876, Electrical 2,283, HVAC 1,634, Plumbing 1,431, Roofing 1,224.

**Lookup or export — which do I use?**

Lookup when you have licence numbers or names: fill 'License number or name' (or the batch list). Names match anywhere in the company name and in the DBA, and both are searched. Export when you want a list: leave that field empty and set filters.

**Does it include expired or revoked licences?**

No. The board's search lists current licences only (17,494 of the 17,495 on 2026-10-12 expired later than that day), and it publishes no status field, so the status column is always empty. A licence that is not in the search returns no row.

**How do I name a classification?**

By its name or a word from it: 'roofing', 'hvac', 'electrical', 'general building', 'finished carpentry'. An exact name matches only itself, so 'electrical' does not also return Sign Installation (No Electrical); a word like 'sign' matches every class containing it. A value that matches none of the 63 classes is dropped and logged.

**Does it include out-of-state contractors?**

Yes: 7,967 of the 17,495 licences (45.5%) have a mailing address outside West Virginia, most often Ohio (1,638), Pennsylvania (1,549), Virginia (993) and Maryland (880). Tick 'West Virginia mailing addresses only' to drop them, or use the county 'Out of State' to get only them.

**How am I charged?**

$0.004 per licence returned. The default export returns 500 licences ($2.00); Kanawha County roofing contractors were 64 ($0.26) on 2026-10-12. Rows explaining an outage or an unrecognised filter are free.

### Which actor to choose

Part of the contractor-data suite — pick the one that fits your goal:

- **Ohio Contractor License Lookup & Leads Scraper (OCILB)** — You need Ohio's electrical, HVAC, plumbing, hydronics and refrigeration contractors — the active OCILB roster with phone.
- **DC Contractor License Lookup & List Scraper (DLCP)** — You need contractors licensed in Washington, DC — every active DLCP general contractor and home improvement licence.
- **Delaware Contractor License Lookup & List Scraper (DOR + DPR)** — You need Delaware contractors — DOR business licences plus DPR electrical, plumbing and HVACR licences, by city or ZIP.
- **Mississippi Contractor License Lookup & Leads Scraper (MSBOC)** — You need Mississippi contractors — the active MSBOC roster with phone, street address and classifications, by county or class.
- **Arizona Contractor License Lookup & Leads Scraper (ROC)** — You need Arizona contractors — every active ROC licence with phone, address, class and qualifying party.
- **Iowa Contractor Registration Lookup & Leads Scraper (DIAL)** — You need Iowa contractors — every active DIAL registration statewide, with phone and email, filtered by trade, county, city or ZIP.
- **Nebraska Contractor Registration Lookup & Leads Scraper (NDOL)** — You need Nebraska contractors — every current NDOL registration, by service and county, with phone on request.
- **Colorado Electrical & Plumbing License Lookup & List Scraper** — You need Colorado electrical or plumbing licences — contractors, masters and journeymen statewide, with status and public disciplinary actions.
- **Maryland Contractor License Lookup & List Scraper (MHIC)** — You need Maryland home improvement contractors — every active MHIC licence with street address and expiry, by city or ZIP.
- **New Jersey Contractor License Lookup & Export (DCA)** — You need New Jersey contractors — active DCA home improvement, electrical, master plumber and HVACR licences statewide or by city, with street address and owner for home improvement firms.

### Guides & use cases

Written up on **[scrapebench.dev](https://scrapebench.dev)** — the bench that runs and verifies this actor against the live source every night:

- **How-to:** [How to run West Virginia Contractor License Lookup & Leads Scraper (WVCLB)](https://scrapebench.dev/guides/how-to-west-virginia-contractor-license-lookup/)
- **Use case:** [Export Kanawha County, West Virginia Roofing Contractors](https://scrapebench.dev/use-cases/kanawha-county-roofing-contractors/)
- **Use case:** [Verify West Virginia Contractor Licenses](https://scrapebench.dev/use-cases/west-virginia-license-verification/)

More actors, coverage and nightly verification results: **[scrapebench.dev](https://scrapebench.dev)**

### Works with AI assistants (MCP)

Callable as an MCP tool, so Claude, Cursor, VS Code Copilot and other MCP clients can run it directly. Grab the config from the [MCP tab](https://apify.com/scrapebench/west-virginia-contractor-license-lookup/api/mcp) on this page — Apify hosts the server and keeps that snippet current, and OAuth signs you in on first connect, so no API token goes in your config file.

Then just ask:

> "List the West Virginia roofing contractors licensed in Kanawha County, with phone and mailing address."

That input returned 64 licences on 2026-10-12. With no filters and no name it exports the whole state (17,495 licences), so set a county or classification before running it from an agent. Runs started this way bill exactly like any other run.

# Changelog

This Actor's version history is a separate document: https://apify.com/scrapebench/west-virginia-contractor-license-lookup/changelog.md

# Actor input Schema

## `query` (type: `string`):

A WVCLB licence number ('WV038157', or just '38157'), or part of a company or DBA name ('Almost Heaven'). Names match anywhere in the company name and in the DBA. Leave empty to run an export instead.

## `queries` (type: `array`):

Several lookups in ONE run, one per line. Combined with the field above if you fill both.

## `county` (type: `string`):

A West Virginia county ('Kanawha', 'Berkeley County'), or 'Out of State' / 'International' for the board's non-WV licences. A value that is not one of these is dropped and logged.

## `counties` (type: `array`):

Several counties in ONE export.

## `classification` (type: `string`):

A WVCLB classification name or a word from one: 'roofing', 'hvac', 'electrical', 'general building', 'siding'. An exact name matches only itself ('electrical' does not also take SIGN INSTALLATION (NO ELECTRICAL)). A value that matches none of the board's 63 classifications is dropped and logged.

## `classifications` (type: `array`):

Several classifications in ONE export, e.g. roofing and siding.

## `city` (type: `string`):

Mailing-address city, exact match ignoring case and punctuation, e.g. 'Charleston' (which does not include South Charleston).

## `cities` (type: `array`):

Several cities in ONE export.

## `westVirginiaAddressesOnly` (type: `boolean`):

Out-of-state contractors hold WV licences: 7,967 of 17,495 (45.5%, 2026-10-12) have a mailing address outside West Virginia. Tick to drop them.

## `maxResults` (type: `integer`):

EXPORT: cap on licences for the WHOLE run — your spend control (17,495 licences statewide on 2026-10-12; set 100000 to take everything that matches). LOOKUP: cap per name or number (default 50).

## `proxyConfiguration` (type: `object`):

Not needed: the board's search answers Apify's own IPs (measured 2026-10-12). Leave it off unless a run reports that the board refused it.

## Actor input object example

```json
{
  "query": "WV038157",
  "queries": [],
  "county": "Kanawha",
  "counties": [],
  "classification": "roofing",
  "classifications": [],
  "cities": [],
  "westVirginiaAddressesOnly": false,
  "maxResults": 500,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Each row is one WVCLB licence: company, DBA, phone, mailing address, county, classifications and expiry date.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "maxResults": 500,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapebench/west-virginia-contractor-license-lookup").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "maxResults": 500,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapebench/west-virginia-contractor-license-lookup").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "maxResults": 500,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call scrapebench/west-virginia-contractor-license-lookup --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapebench/west-virginia-contractor-license-lookup"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/VUFALCUzarxpecGLk/builds/9FO8hGY17GQlpozzt/openapi.json
