# NC General Contractor License Scraper (`muhammadafzal/nc-licensing-board-general-contractors-scraper`) Actor

Scrape the official North Carolina Licensing Board for General Contractors website portal by license number or business name. Returns public status, expiration, limitation, classifications, qualifiers, address, phone, and source URLs.

- **URL**: https://apify.com/muhammadafzal/nc-licensing-board-general-contractors-scraper.md
- **Developed by:** [Muhammad Afzal](https://apify.com/muhammadafzal) (community)
- **Categories:** Lead generation, Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 license records

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## NC General Contractor License Scraper

Search the official North Carolina Licensing Board for General Contractors (NCLBGC) public registry and return structured license records for contractor verification, lead research, compliance workflows, and directory enrichment.

### What it extracts

Each default-dataset item represents one license detail record and includes:

| Field | Description |
| --- | --- |
| `licenseName`, `alternateName` | Public licensee/company names |
| `licenseNumber`, `status`, `renewalDate` | License identity and public status fields |
| `limitation`, `classifications` | License limitation and classifications |
| `qualifiers` | Public qualifier names associated with the license |
| `address1`, `address2`, `city`, `state`, `zip`, `county` | Public business address fields |
| `telephone` | Public phone field, when supplied |
| `sourceUrl`, `sourceSearchUrl`, `scrapedAt` | Provenance and UTC collection timestamp |

### Input

Provide at least one search filter. The Board supports combinations of filters:

```json
{
  "licenseName": "Acme Builders",
  "county": "Wake",
  "maxResults": 25,
  "maxPages": 5
}
```

For an exact lookup:

```json
{ "licenseNumber": "12345", "maxResults": 1 }
```

`maxResults` defaults to 25 and is capped at 500. `maxPages` defaults to 5 and is capped at 25. The scraper uses the Board’s own public JSON search and detail endpoints; it does not require login credentials or cookies.

### Output and pricing

Records are written to the default dataset. The `OUTPUT` key-value record contains `recordsCollected`, `chargedEvents`, `pagesVisited`, `blocked`, filters, and warnings.

| Event | Price |
| --- | ---: |
| Actor start | $0.00005 |
| License record | $0.003 per delivered record |

Examples: one exact license lookup costs up to $0.00305; 25 delivered records cost up to $0.07505, excluding any Apify platform proxy or runtime usage outside the event prices.

### Reliability and limitations

The Actor submits the public search form at the official NCLBGC portal, parses the returned HTML result table, then loads each public account-detail and qualifier page. It retries through an Apify US proxy when direct website access fails, deduplicates by license number, validates each record before writing, and stops at the configured result limit. A valid search with no matches returns zero records and a diagnostic summary. HTTP errors, timeouts, malformed HTML, TLS failures, or access blocks are reported in `OUTPUT`; the Actor never fabricates license records.

The Board controls the public fields and availability of its registry. This Actor is a read-only interface to public records, not a legal determination that a contractor is currently authorized for a particular project. Verify important licensing decisions with NCLBGC and comply with applicable laws, terms, and privacy requirements.

### Source

Official source: https://portal.nclbgc.org/Public/Search

### Use cases

- Build public prospect lists and qualify organizations or professionals before responsible outreach.
- Compare listings, locations, availability, and market signals for property research.
- Run a one-off research job and export the structured result as JSON, CSV, Excel, XML, or RSS from Apify.
- Schedule the same input to monitor changes over time and send completed datasets to a webhook or integration.
- Feed schema-shaped records into a database, spreadsheet, BI tool, or AI workflow with the source URL retained for verification.

### Run NC General Contractor License Scraper with the Apify API

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('muhammadafzal/nc-licensing-board-general-contractors-scraper').call({
  "licenseName": "Acme Builders",
  "licenseNumber": "12345",
  "county": "Wake",
  "address": "Raleigh",
  "maxResults": 25,
  "maxPages": 5,
  "requestDelayMs": 500
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

You can also run the Actor from Apify Console, schedules, webhooks, the REST API, Make, Zapier, n8n, or the hosted Apify MCP server.

### Frequently asked questions

#### Can I schedule NC General Contractor License Scraper?

Yes. Use an Apify schedule to run the same saved input at a chosen interval, then connect a webhook or integration to process the dataset when the run finishes.

#### How should I test a new input?

Begin with the prefilled example or a small limit. Confirm that the output fields, source coverage, runtime, and live charges match your workflow before increasing the scope.

#### How do I export the results?

Open the run's default dataset in Apify Console and export JSON, CSV, Excel, XML, or RSS. Applications can retrieve the same records through the Apify API client or REST dataset endpoint.

#### Can an AI agent call this Actor?

Yes. Add `muhammadafzal/nc-licensing-board-general-contractors-scraper` through the hosted Apify MCP server or call it through the API. The Actor's input and dataset schemas help agents construct valid requests and interpret returned records.

# Actor input Schema

## `licenseName` (type: `string`):

Use this when searching a contractor or company name. Enter a name such as Acme Builders; omit it when using a license number, county, or address only.

## `licenseNumber` (type: `string`):

Use this for a precise lookup of an NC general contractor license. Enter the board number as shown, such as 12345; omit it for name or location discovery.

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

The current public NCLBGC website form does not expose a county field. Do not use this alone; it is retained only for compatibility and is ignored when combined with another search filter.

## `address` (type: `string`):

Use this to search the public licensee address field. Enter a street, city, or other address text; this is not a geocoded radius search.

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

Use this to cap delivered license records and PPE cost. The default is 25 and the maximum is 500.

## `maxPages` (type: `integer`):

Use this to bound pagination. The default is 5 pages; each page is read from the official search API and can return up to the board's page size.

## `requestDelayMs` (type: `integer`):

Use this to control the pause between detail requests. The default is 500 ms; allowed values are 250–5000 ms.

## Actor input object example

```json
{
  "licenseName": "Acme Builders",
  "licenseNumber": "12345",
  "county": "Wake",
  "address": "Raleigh",
  "maxResults": 25,
  "maxPages": 5,
  "requestDelayMs": 500
}
```

# Actor output Schema

## `summary` (type: `string`):

JSON summary stored in OUTPUT, including records, warnings, pages, and billing counts.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("muhammadafzal/nc-licensing-board-general-contractors-scraper").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("muhammadafzal/nc-licensing-board-general-contractors-scraper").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 '{}' |
apify call muhammadafzal/nc-licensing-board-general-contractors-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,muhammadafzal/nc-licensing-board-general-contractors-scraper"
        }
    }
}

```

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/wflsuupVLPL4voqkI/builds/ZYkkxUVFrExfsTgAw/openapi.json
