# Arkansas Contractor License Lookup Scraper (`automation-lab/arkansas-contractor-license-records`) Actor

Search the official Arkansas contractor registry by business name, registry ID or license prefix. Export source validity, expiration, classifications, restrictions and provenance for vendor credential checks.

- **URL**: https://apify.com/automation-lab/arkansas-contractor-license-records.md
- **Developed by:** [Automation Lab](https://apify.com/automation-lab) (community)
- **Categories:** Business
- **Stats:** 2 total users, 1 monthly users, 11.5% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.80 / 1,000 contractor credential records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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?

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

## Arkansas Contractor License Lookup Scraper

Use this **Arkansas contractor license lookup** to check vendors against the official Arkansas Contractors Licensing Board (ACLB) registry. Search by business name, registry ID or the first six digits of a license number. Export the source's validity label, license expiration, classifications, restrictions and public business contact details with provenance.

This Actor is for procurement teams checking vendor credentials, compliance analysts preparing repeat checks, and construction operations teams reconciling contractor records. It returns what the board publishes at run time, not a legal certification or a historical license database.

### Who is it for?

Procurement teams can verify named vendors before onboarding. Compliance analysts can reconcile credential identifiers across repeat snapshots. Construction operations teams can review classifications and restrictions before requesting board confirmation for ambiguous records. This is not a cold-contact list generator.

### Why use this Actor?

- Preserve the board's own validity label instead of guessing status from an expiration date.
- Keep leading zeros in license identifiers.
- Deduplicate overlapping queries without charging twice for the same delivered credential record.
- Inspect a coverage summary when the source caps a broad search or your result limit stops collection.
- Compare scheduled exports in your own system using registry ID and full license number.

### Getting started

1. Enter one or more query objects.
2. Use exactly one selector in each object.
3. Set a global `maxItems` appropriate for your vendor list.
4. Start the Actor and inspect its run status.
5. Export the default dataset as JSON, CSV or Excel using Apify's dataset tools.
6. Read `SUMMARY` in the key-value store before interpreting a broad search as complete.

The prefilled example is a single official registry-ID lookup:

```json
{
  "queries": [{ "registryId": "23" }],
  "maxItems": 10
}
```

### Arkansas contractor license lookup inputs

| Input | Meaning |
|---|---|
| `queries` | Required array of 1–100 query objects. Exactly one selector per object. |
| `businessName` | Case-insensitive substring of the displayed business name. Leading/trailing whitespace is trimmed. No whole-word or exact-field claim. |
| `registryId` | Exact numeric registry ID as a string. Numeric comparison ignores leading zeros. |
| `licenseNumber` | Exactly the first six digits of the license number, including leading zeros. Full ten-digit license values are rejected. |
| `maxItems` | Global cap on accepted unique records, default 100, range 1–5000. Zero/unlimited is unsupported. |

Different queries are ANY, not ALL. You cannot combine selectors within one query. Unsupported fields and malformed values fail validation rather than being silently ignored. Internal whitespace is not rewritten in the query; source text whitespace is normalized.

A name query matches only the displayed business-name cell, not address, classification, officers or every DBA in the nightly roster. Prefer an ID or license prefix for repeat vendor checks.

```json
{
  "queries": [
    { "businessName": "axioo" },
    { "licenseNumber": "001219" },
    { "registryId": "25" }
  ],
  "maxItems": 10
}
```

### Extracted data

| Field | Interpretation |
|---|---|
| `businessName` | Displayed source business name. |
| `registryId` | Source ID as text; occasionally blank upstream. |
| `sourceValidity` | Source Valid cell: observed values include Yes, No, Expired, Inactive, Call, Extended and blank. |
| `licenseNumber` | Full source license text, preserving zeros. |
| `registrationNumber`, `licenseType` | Board's registration and type fields. |
| `expirationDate`, `licenseExtendedTo` | Source date strings, generally MM/DD/YYYY; no derived status calculation. |
| `classifications` | Complete classification text. Commas within classification names are not split into fabricated categories. |
| `restricted`, `suggestedBidLimit` | Source restriction and bid-limit text. Blank is unknown/not supplied, not affirmative clearance. |
| `address`, `city`, `state`, `county`, `zip` | Public mailing/location fields. An Arkansas licensee may have an out-of-state address. |
| `phone`, `fax` | Public source contact text. Email and officers are not included by this search route. |
| `sourceUrl`, `scrapedAt` | Registry endpoint and ISO extraction timestamp. |
| `matchedQuery` | First accepted query that produced the deduplicated row. |

Missing source cells are empty strings. Schema fields allow null for interoperability, but this implementation preserves empty source cells as empty strings.

### Real output example

An official registry-ID lookup returned the following business credential fields:

```json
{
  "businessName": "AXIOO CONSTRUCTION, INC.",
  "sourceValidity": "Yes",
  "registryId": "23",
  "licenseNumber": "0012190427",
  "licenseType": "Commercial",
  "expirationDate": "04/30/2027",
  "classifications": "Heavy Construction, Municipal & Utility Construction, Retaining Walls",
  "restricted": "",
  "suggestedBidLimit": "Unlimited",
  "city": "MULBERRY",
  "state": "AR",
  "sourceUrl": "http://aclb2.arkansas.gov/clbsearch.php",
  "matchedQuery": { "registryId": "23" }
}
```

This excerpt omits public contact fields and the changing `scrapedAt` timestamp for brevity. Actual records include the complete documented schema.

### Coverage, deduplication and limits

The board caps each search at 5,000 rows and exposes no pagination on this surface. Broad queries may omit relevant rows beyond that cap. This Actor does not claim statewide exhaustive coverage or silently switch to the nightly CSV roster, which lacks equivalent source-validity fields.

The run stops accepting records when global `maxItems` is reached. Later queries may remain unprocessed. Deduplication uses registry ID plus license number; rows without an ID use business name, address and license number. If a credential appears in several queries, only its first matched query is retained.

`SUMMARY` includes requested/processed queries, source match counts, source-cap flags, relevant rows, emitted counts and whether the run limit was reached. Source counts can exceed accepted counts because matching and deduplication are defensive. A failed run may have partial rows from earlier queries; do not label them a complete successful result.

### How much does it cost to verify Arkansas contractor licenses?

Pay-per-event pricing has a **$0.005 start fee per valid run**, plus a tier-dependent fee per unique delivered contractor credential record. Invalid input fails before the start event. Valid no-result searches still have the start fee, but no item charge. Duplicates and rejected rows have no item charge.

| Plan tier | Per credential record |
|---|---:|
| FREE | $0.0092 |
| BRONZE | $0.008 |
| SILVER | $0.00624 |
| GOLD | $0.0048 |
| PLATINUM | $0.0048 |
| DIAMOND | $0.0048 |

Example BRONZE run totals, including the start event:

| Delivered records | Total event charge |
|---|---:|
| 1 | $0.013 |
| 10 | $0.085 |
| 100 | $0.805 |

These are Actor event prices, not a promise about your plan's separate platform/storage charges. Apify's run spending limit can stop paid output early; check the run and dataset before assuming a full export.

### Integrations

Export dataset rows into a spreadsheet for procurement review. Use an Apify webhook after a successful run to trigger your own CRM, warehouse or compliance pipeline. For recurring checks, schedule a saved input and compare the resulting registry IDs/license numbers and source-validity fields downstream.

The Actor does not itself send alerts, store history or detect changes across runs. Your integration owns that comparison and should retain `scrapedAt`, `sourceUrl` and coverage summaries with each snapshot.

### API usage

Use a private environment variable for your Apify token. Never place credentials in query objects.

```bash
curl -X POST \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  'https://api.apify.com/v2/acts/automation-lab~arkansas-contractor-license-records/runs' \
  -d '{"queries":[{"registryId":"23"}],"maxItems":100}'
```

The response supplies a run ID, not completed dataset rows. Follow that run until terminal status, then fetch its `defaultDatasetId`.

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/arkansas-contractor-license-records')
  .call({ queries: [{ registryId: '23' }], maxItems: 100 });
if (run.status !== 'SUCCEEDED') throw new Error(`Run ${run.id}: ${run.status}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems({ limit: 100 });
console.log(items);
```

```python
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/arkansas-contractor-license-records').call(
    run_input={'queries': [{'registryId': '23'}], 'maxItems': 100})
if run['status'] != 'SUCCEEDED':
    raise RuntimeError(run['status'])
print(client.dataset(run['defaultDatasetId']).list_items(limit=100).items)
```

### Hosted MCP use

Select the stable Actor-specific tool subset:

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

For **Claude Desktop**, **Cursor**, and **VS Code**, use the equivalent client configuration below, adapting your client's remote-MCP authentication settings:

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

Configure authentication in your client's protected settings. Discover actual tool names and arguments with `tools/list`; Actor selection also supplies run/data/abort tools, not exactly one tool. Discovery is read-only, not execution permission.

Example prompt (when execution is authorized): “Look up Arkansas contractor registry ID 23, return at most 10 records, and show the source validity, license number and expiration.” Start once, retain the returned run/storage IDs, and follow the same run. For `call-actor`, `waitSecs` is 0–45 seconds; a nonterminal response is not a failure. Poll that run with bounded backoff (2, 4, 8 seconds, capped at 10) and a 120-second consumer deadline. Do not restart after a client timeout; recover the known run or report uncertainty.

Once successful, fetch dataset pages with explicit offset, limit and fields. Example consumer context budget: pages of 20 source rows, at most 100 rows and 64 KiB of UTF-8 result content admitted to model context, whichever comes first. Enforce the byte ceiling host-side, including oversized single rows. Report continuation offset and partial/truncated status. Keep full exports outside model context. This is a consumer context limit, not a reduction of Actor collection capabilities; clients unable to intercept responses cannot promise a hard byte guarantee. No numeric token-savings claim is made.

### Reliability and troubleshooting

Requests are sequential. Transport resets/timeouts, temporary DNS failures, HTTP 429 and server errors receive at most two retries with bounded backoff. Permanent HTTP errors, changed columns and unrecognized pages fail visibly. There is no hidden paid proxy or browser fallback.

The legacy official registry currently serves this workflow over **unencrypted HTTP**. The board's HTTPS navigation page links to that endpoint; HTTPS on the legacy host did not respond during implementation. Public input and returned data can lack transport integrity/confidentiality. Do not submit sensitive or secret values. This Actor does not present HTTP results as cryptographically authenticated evidence.

If a name search yields zero rows, try a shorter substring or a known registry ID. A valid empty search succeeds and emits a zero-count summary. If the registry changes or is unavailable, retry later or contact the board; do not interpret an error as “unlicensed.” For “Call,” blank or ambiguous validity, confirm with the board before a credential decision.

### Legality and responsible use

Use public records in accordance with applicable law, source terms and your organization's compliance policy. The Actor is not affiliated with or endorsed by the Arkansas Contractors Licensing Board. A listing is not permission to contact people indiscriminately. The source may change and the records can contain errors or stale information.

Failed operations send sanitized diagnostic input, exceptions and actor/build/run IDs to our private GlitchTip service for repair. Secret fields and URL queries are removed, and reports are retained for 30 days.

### Data handling and support

No AI model processes queries or source records at runtime. The generated illustration is a build-time asset, not an inference service. Operational dependencies are Apify hosting/storage, the official public registry, and private GlitchTip diagnostics; there is no third-party paid search API or hidden proxy fee.

Queries and credential rows remain in your run's Apify storage under your account retention settings until you delete them or your retention policy removes them. There is no cross-run cache or external credential-history database. Delete the run's dataset and key-value store to remove its stored results; Apify's backup/account retention rules remain applicable. Diagnostic reports are retained for 30 days. Runtime logs contain counts and errors, not full rows or query values.

For help, open an Actor issue on Apify with your run ID and a nonsensitive reproduction selector. Do not post tokens or private inputs. Source outages and ambiguous license labels should be checked with the board.

### FAQ

**Can I enter the full license number?** No. Submit its first six digits as text, including zeros; the returned row contains the full source number.

**Does an expiration date prove current validity?** No. Read the board's separate validity label and any extension field; ambiguous statuses require direct board verification.

**Can I download every Arkansas contractor?** Not from this Actor. Searches are capped upstream and broad results can be incomplete. Narrow your query and inspect the summary.

**Does this include historical changes or automated alerts?** No. Schedule repeated runs and compare snapshots in your own integration.

### Related Actors

For a different jurisdiction, [Tennessee Contractor License Lookup](https://apify.com/automation-lab/tennessee-contractor-license-lookup) covers Tennessee records. It does not include Arkansas credentials. [Louisiana Contractor Licenses Scraper](https://apify.com/automation-lab/louisiana-contractor-license-leads-scraper) supports Louisiana registry searches. Keep each state's source and credential identity separate when combining outputs.

# Changelog

This Actor's version history is a separate document: https://apify.com/automation-lab/arkansas-contractor-license-records/changelog.md

# Actor input Schema

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

Supply 1–100 objects, each with exactly one string: businessName (case-insensitive substring of displayed business name, whitespace trimmed), registryId (exact numeric ID), or licenseNumber (exact first six digits, preserving zeros). Multiple queries are ANY; output retains only the first matching query after deduplication. Unsupported keys or combined selectors fail validation.

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

Global maximum unique registry-ID/license pairs after matching and deduplication across all queries; records lacking an ID use name/address/license identity. Default 100; 1–5000 supported; zero/unlimited is not supported. The source caps each search at 5000 and offers no pagination. SUMMARY reports cap and run-limit observations; a limit may leave later queries unprocessed.

## Actor input object example

```json
{
  "queries": [
    {
      "registryId": "23"
    }
  ],
  "maxItems": 10
}
```

# Actor output Schema

## `overview` (type: `string`):

Deduplicated source credential dataset in the overview view.

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

Per-query coverage, source caps and run-limit summary.

# 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 = {
    "queries": [
        {
            "registryId": "23"
        }
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/arkansas-contractor-license-records").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 = {
    "queries": [{ "registryId": "23" }],
    "maxItems": 10,
}

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

```

## MCP server setup

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

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/7L1p0gB5Qv9ozsNNN/builds/6Ic8z3HQZrUZ0BCoO/openapi.json
