# Alabama General Contractor Licenses Scraper (`automation-lab/alabama-general-contractor-license-registry`) Actor

Download and filter the official Alabama general contractor roster with license identity, contact, bid limit, classification, expiration, extension, status, and provenance.

- **URL**: https://apify.com/automation-lab/alabama-general-contractor-license-registry.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $13.68 / 1,000 item extracteds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Alabama General Contractor Licenses Scraper

Download and filter **Alabama general contractor licenses** from the official Alabama Licensing Board for General Contractors (LBGC) roster. The Actor turns the board's full CSV into typed records for contractor verification, vendor onboarding, compliance review, and recurring expiration checks.

One source request returns license identity, public address and contact fields, bid limit, specialty/classification, expiration, extension, derived standing, and provenance. You can export the result as JSON, CSV, Excel, XML, or RSS from the Apify dataset.

### What does this Actor do?

1. Downloads the current official LBGC License Verification List.
2. Validates that the response is the expected government CSV.
3. Normalizes dates and empty values.
4. Derives `licenseStatus` from the later of expiration and extension dates.
5. Applies all requested filters locally to the same roster snapshot.
6. Saves up to `maxItems` matching records to the default dataset.

The Actor covers the Alabama LBGC commercial general-contractor and subcontractor roster. It does not claim to cover residential home-builder licenses administered by a different board.

### Who is it for?

- Procurement teams validating vendors before onboarding or renewal.
- General contractors checking subcontractor license information.
- Compliance teams reviewing expiration and extension dates.
- Insurers and lenders enriching a contractor record with public license data.
- Marketplaces verifying Alabama contractor suppliers.
- Analysts building a current classification or geographic roster.

### Why use it?

The official roster is authoritative but not shaped for recurring automation. This Actor provides:

- one structured item per license;
- combined list and detail fields from the official CSV;
- filters for names, exact licenses, cities, states, and classifications;
- active/expired and expiration-cutoff filtering;
- normalized ISO dates alongside the published source fields;
- stable provenance URLs and retrieval timestamps;
- bounded output and pay-per-result billing.

No AI enrichment or third-party identity matching is added. Missing government values stay `null`.

### Extracted Alabama contractor data

| Field | Meaning |
| --- | --- |
| `licenseNumber` | Official LBGC license number, including any prefix |
| `businessName` | Licensed business name |
| `address` | Public mailing or street address |
| `city`, `state`, `postalCode` | Published business location |
| `phone`, `fax` | Public business contact details |
| `bidLimit` | Published bid limit, such as `U UNLIMITED` |
| `specialty` | Complete specialty/classification text |
| `classifications` | Specialty text split into convenient entries |
| `expirationDate` | Published expiration normalized to `YYYY-MM-DD` |
| `extensionDate` | Published extension normalized to `YYYY-MM-DD` |
| `effectiveExpirationDate` | Later of expiration and extension |
| `licenseStatus` | `ACTIVE`, `EXPIRED`, or `UNKNOWN`, derived as of run date |
| `sourceUrl` | Official roster page |
| `sourceDownloadUrl` | Official CSV endpoint used by the run |
| `sourceAgency` | Alabama LBGC |
| `retrievedAt` | ISO timestamp for this roster snapshot |

### How to get started

1. Open the Actor input page.
2. Add one or more filters, or leave filters empty to export the roster from the beginning.
3. Set `maxItems` to bound the number of output records.
4. Keep Apify Proxy enabled for reliable access to the Alabama state host.
5. Click **Start**.
6. Open the **Dataset** tab and export the records in your preferred format.

A useful first run is:

```json
{
  "companyNames": ["DUNN CONSTRUCTION"],
  "maxItems": 10
}
```

### Input parameters

| Input | Type | Default | Description |
| --- | --- | --- | --- |
| `companyNames` | string\[] | `[]` | Business-name substring filters, case-insensitive |
| `licenseNumbers` | string\[] | `[]` | Exact LBGC license numbers |
| `cities` | string\[] | `[]` | Exact cities, case-insensitive |
| `states` | string\[] | `[]` | Exact business-address state abbreviations |
| `classifications` | string\[] | `[]` | Specialty code/text substring filters |
| `expiresBefore` | string | unset | Keep licenses effective on or before a `YYYY-MM-DD` cutoff |
| `includeExpired` | boolean | `true` | Set false to remove already expired records |
| `maxItems` | integer | `100` | Save 1–20,000 matching records |
| `proxyConfiguration` | object | Apify Proxy on | Network routing for the state roster |

Values within one filter are combined with OR. Different filters are combined with AND. For example, `states: ["AL"]` plus `classifications: ["BC"]` keeps Alabama-address records whose specialty contains `BC`.

### Example output

This shortened item came from the documented company-name example:

```json
{
  "licenseNumber": "8",
  "businessName": "DUNN CONSTRUCTION CO INC",
  "address": "P O BOX 11967",
  "city": "BIRMINGHAM",
  "state": "AL",
  "postalCode": "35202",
  "phone": "(205) 592-3866",
  "fax": "(205) 592-4632",
  "bidLimit": "U UNLIMITED",
  "specialty": "BC: BUILDING CONSTRUCTION, H/RR: HEAVY AND RAILROAD, HS: HIGHWAYS AND STREETS, MU: MUNICIPAL AND UTILITY",
  "classifications": [
    "BC: BUILDING CONSTRUCTION",
    "H/RR: HEAVY AND RAILROAD",
    "HS: HIGHWAYS AND STREETS",
    "MU: MUNICIPAL AND UTILITY"
  ],
  "expirationDate": "2026-09-30",
  "extensionDate": null,
  "effectiveExpirationDate": "2026-09-30",
  "licenseStatus": "ACTIVE",
  "sourceUrl": "https://licensesearch.alabama.gov/genconbd",
  "sourceAgency": "Alabama Licensing Board for General Contractors (LBGC)",
  "retrievedAt": "2026-09-12T14:14:18.480Z"
}
```

Dates and standing reflect the source and run time. A later run can legitimately return different values.

### How much does it cost to export Alabama contractor licenses?

This is a pay-per-event Actor. Each run has a **$0.005 start fee**, then charges for each contractor record saved. Empty searches incur only the start fee. The final six plan-tier record prices are shown by Apify on the Actor pricing tab; BRONZE is **$0.0228 per record**, with lower rates on higher plans.

Approximate BRONZE examples:

| Useful records | BRONZE calculation |
| ---: | --- |
| 1 | $0.005 + 1 × $0.0228 |
| 10 | $0.005 + 10 × $0.0228 |
| 100 | $0.005 + 100 × $0.0228 |
| 1,000 | $0.005 + 1,000 × $0.0228 |

Set `maxItems` and narrow filters to control the bill. Apify displays the applicable plan-tier price before a Store run.

### Vendor verification workflow

Search by an exact `licenseNumbers` value when a vendor supplied a credential. Save the returned identity, classifications, bid limit, and effective expiration in your onboarding record. A zero-item result means no row matched the current official roster; it is not proof of misconduct and should be reviewed with the board.

### Expiration and compliance workflow

Schedule the same input weekly or monthly with Apify Tasks. Use `includeExpired: false` for currently effective licenses and `expiresBefore` to select an upcoming review window. Compare datasets downstream by `licenseNumber` to identify changed dates, classifications, contacts, or bid limits.

The Actor itself produces current snapshots. It does not send alerts or calculate historical changes.

### Classification and location export

Use a code or descriptive text in `classifications`, such as `BC: BUILDING CONSTRUCTION`, and optionally combine it with `cities` or `states`. The roster includes Alabama-licensed contractors with out-of-state business addresses, so `states: ["AL"]` is a meaningful additional filter rather than an assumed default.

### Integrations

Connect the dataset to:

- Google Sheets or Microsoft Excel for vendor review;
- webhooks for an internal onboarding pipeline;
- Make, Zapier, or n8n for scheduled checks;
- BigQuery, Snowflake, or another warehouse for snapshot comparison;
- a CRM keyed by `licenseNumber`;
- Python or JavaScript compliance jobs through the Apify API.

### Run through the REST API

Replace `<APIFY_TOKEN>` with your token:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~alabama-general-contractor-license-registry/runs?token=<APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"classifications":["BC: BUILDING CONSTRUCTION"],"states":["AL"],"includeExpired":false,"maxItems":25}'
```

Read items after the run succeeds from its `defaultDatasetId`.

### Use from JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/alabama-general-contractor-license-registry').call({
  licenseNumbers: ['8'],
  maxItems: 10,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Use from Python

```python
from apify_client import ApifyClient

client = ApifyClient(token='YOUR_APIFY_TOKEN')
run = client.actor('automation-lab/alabama-general-contractor-license-registry').call(run_input={
    'states': ['AL'],
    'expiresBefore': '2027-12-31',
    'includeExpired': False,
    'maxItems': 50,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### Use with MCP and AI clients

Add the remote Apify MCP server to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/alabama-general-contractor-license-registry"
```

#### Claude Desktop, Cursor, and VS Code setup

Use this same remote-server JSON in **Claude Desktop**, **Cursor**, or **VS Code** (in the MCP servers section supported by that client):

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/alabama-general-contractor-license-registry"
    }
  }
}
```

Example prompts:

- “Find the Alabama LBGC record for license 8 and summarize its expiration and classifications.”
- “Export 50 active Alabama-address building contractors for vendor review.”
- “Return licenses effective on or before 2027-12-31 so I can prepare a review list.”

Treat AI conclusions separately from the official fields returned by the Actor.

### Reliability and failure behavior

The Actor uses the official downloadable roster rather than thousands of detail-page requests. It validates the HTTP status and expected CSV header before accepting data. Transient transport failures receive bounded retries within one coherent datacenter proxy session.

A recognizable but empty filtered result succeeds with zero dataset rows. An invalid input, unreachable source after retries, or unexpected response shape fails the run rather than silently returning a misleading empty dataset.

### Limitations

- Coverage is limited to the roster published by Alabama LBGC.
- `licenseStatus` is derived from published dates; the CSV has no separate standing field.
- `UNKNOWN` means no parseable effective date was available.
- The source can change columns, availability, or records without notice.
- Classification splitting is a convenience view; `specialty` preserves the complete source text.
- The Actor does not provide disciplinary history, bonds, insurance, or residential home-builder records.
- The Actor returns snapshots, not built-in change alerts.

### Responsible use and legality

The source is a public professional-license roster. Use the data for lawful verification, research, procurement, and compliance purposes. Follow applicable privacy, employment, credit, insurance, anti-discrimination, retention, and notice requirements. Do not treat an automated match or no-match as the sole basis for a consequential decision. Consult the Alabama board when authoritative confirmation is required.

### Troubleshooting

**Why did I receive zero records?**

Check whether exact filters are too narrow. `licenseNumbers`, `cities`, and `states` require exact case-insensitive values; company and classification values are substring filters. Try one filter at a time.

**Why does a license show `EXPIRED`?**

The Actor compares the later of expiration and extension with the run date. Review both date fields and confirm consequential decisions with LBGC.

**Why did source access fail?**

Keep the default Apify Proxy configuration enabled. The Actor fails explicitly if the official state host remains unavailable or stops returning its expected CSV.

**Can I download the entire roster?**

Yes. Leave filters empty and increase `maxItems` up to 20,000. The current roster size can change; pay-per-record billing applies to the output.

### FAQ

**How current are the results?**

Each run downloads the official roster at run time. `retrievedAt` records when that snapshot was obtained.

**Are extension dates respected?**

Yes. `effectiveExpirationDate` uses the later of expiration and extension, and status/cutoff filtering uses that effective date.

**Can I filter several companies or classifications at once?**

Yes. Values in the same array use OR logic; filters across fields use AND logic.

**Is a no-match definitive evidence that a contractor is unlicensed?**

No. It only means the current official roster returned no row matching the supplied filters. Check spelling and contact LBGC for authoritative confirmation.

### Related automation-lab Actors

- [North Carolina Contractor License Lookup Scraper](https://apify.com/automation-lab/north-carolina-contractor-license-lookup-scraper) for NCLBGC records.
- [California Contractor License Lookup](https://apify.com/automation-lab/california-contractor-license-lookup-v2) for CSLB status, classifications, bonds, and personnel.
- [Tennessee Contractor License Lookup](https://apify.com/automation-lab/tennessee-contractor-license-lookup) for Tennessee contractor and limited-plumber credentials.

Use a state-specific Actor because agencies publish different fields and license populations.

# Actor input Schema

## `companyNames` (type: `array`):

Keep records whose licensed business name contains any value (case-insensitive). Leave empty for all companies.

## `licenseNumbers` (type: `array`):

Keep exact LBGC license numbers, including prefixes such as S- for subcontractors.

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

Keep exact business cities (case-insensitive), for example Birmingham or Montgomery.

## `states` (type: `array`):

Keep exact two-letter business-address states. The Alabama roster includes out-of-state licensees.

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

Keep rows whose specialty text contains any code or phrase, such as BC or BUILDING CONSTRUCTION.

## `expiresBefore` (type: `string`):

Optional YYYY-MM-DD cutoff applied to the effective expiration date (extension when later).

## `includeExpired` (type: `boolean`):

Include records whose expiration or extension date has passed.

## `maxItems` (type: `integer`):

Maximum matching contractor records to save.

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

Apify Proxy is enabled by default for reliable access to the Alabama state roster.

## Actor input object example

```json
{
  "companyNames": [
    "DUNN CONSTRUCTION"
  ],
  "licenseNumbers": [],
  "cities": [],
  "states": [],
  "classifications": [],
  "includeExpired": true,
  "maxItems": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset containing normalized Alabama general contractor license records.

# 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 = {
    "companyNames": [
        "DUNN CONSTRUCTION"
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/alabama-general-contractor-license-registry").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 = {
    "companyNames": ["DUNN CONSTRUCTION"],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/alabama-general-contractor-license-registry").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 '{
  "companyNames": [
    "DUNN CONSTRUCTION"
  ],
  "maxItems": 10
}' |
apify call automation-lab/alabama-general-contractor-license-registry --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/alabama-general-contractor-license-registry"
        }
    }
}
```

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/urDHTJWlhh7MICNrT/builds/1YCWUiXYmS5PkkJHP/openapi.json
