# Arizona Contractor License Lookup & Export (`wellbuilt_zythem/arizona-contractor-license-lookup`) Actor

Every AZ ROC-licensed contractor in Arizona, refreshed from the board's daily file. Export a whole classification (roofing, electrical, plumbing, HVAC, pools) or verify a list of names or licence numbers. Status, expiry date, address. No phone: the ROC does not publish it. Measured coverage

- **URL**: https://apify.com/wellbuilt\_zythem/arizona-contractor-license-lookup.md
- **Developed by:** [Carlos Escanez](https://apify.com/wellbuilt_zythem) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 licence records

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

## Arizona Contractor License Lookup & Export — Arizona Registrar of Contractors (AZ ROC)

**Paste a list of names or licence numbers and get one row per matching Arizona licence. Or export every licensed roofing contractor in Arizona in one run.** Read straight from the official register, normalised into one clean row.

### See it run

https://youtu.be/07g\_67B52DM

### Questions this answers

- Is this roofing contractor's license active in Arizona right now, and when does it expire?
- Check these 500 subcontractor names against the Arizona board before we put them on site.
- Export every licensed roofing, electrical, plumbing contractor in Arizona.
- Which Arizona licences expire in the next 60 days?

### What Arizona actually publishes

Measured on real rows pulled from the board, not on what its documentation says. **A field the board does not publish stays empty; the Actor never guesses one.**

| Field | Published |
|---|---|
| Licence number, status, trade | yes |
| Expiry date | yes |
| Street address | yes |
| City and ZIP | yes |
| County | no |
| Phone | no |
| Email | no |
| Insurance or bond expiry | no |

**Arizona publishes no phone number.** Not in the search results and not on the licence page. Rows carry name, address, licence number, trade, status and expiry date, and the phone column is empty. That is the register, not a gap in this Actor: what you get is a verification and renewal-window tool, not a calling list.

### Trades covered

- General building and engineering (A, B, KA, KB)
- Electrical (CR-11, C-11, R-11)
- Plumbing, solar liquid systems included
- Air conditioning, refrigeration and heating
- Roofing (CR-42, C-42, R-42)
- Swimming pools, spas and pool service
- Elevators (CR-12, C-12, R-12)
- Low voltage communication systems (CR-67, C-67, R-67)
- Minor home improvements, remodeling and repairs
- As restricted by the Registrar (CR-5, KE, KO)
- Painting and wall covering (CR-34, C-34, R-34)
- Concrete (CR-9, C-9, R-9)
- Hardscaping and irrigation systems (CR-21, C-21, R-21)
- Excavating, grading and oil surfacing (CR-2, R-2, A-5)
- Carpentry and finish carpentry (CR-7, CR-60 and friends)

A trade the board does not license is not in the list, and the Actor will not invent it.

### Two modes

**Lookup.** One name or licence number per line. A licence number matches exactly; a name matches any licensee or business containing it. Every match comes back as its own row with the query it matched, so a list of 800 subcontractors comes back as a checked list.

**Export.** Pick a trade (or all of them) and get every licence in Arizona, with `onlyActive`, `onlyWithPhone` and `onlyExpiringSoon` (next 60 days) filters and a `maxResults` cap.

### What every row carries

`state`, `licenseNumber`, `name`, `businessName`, `tradeLabel`, `status`, `isActive`, `expirationDate`, `daysToExpiry`, `isExpiringSoon`, `address`, `city`, `zip`, `county`, `phone`, `email`, `sourceUrl`, `scrapedAt`, plus `matchedQuery` in lookup mode. Dates are ISO, phones are E.164, status is normalised so `ACTIVE` means active on every board.

### Built for verification

- **Every query comes back as a row**, matched or not, with `matchedQuery` to join it to your list.
- **No match, no charge.**
- **Status normalised** so `isActive` means the same thing as on every other board; the board's own status text is kept.
- **Source URL on every row**, pointing at the board's page for that licence: the primary source for a compliance file.
- **Coverage printed by the run**, per field, in `RUN_SUMMARY`: what you actually received, not what a README promises.
- **Incomplete runs say so**: a board that did not answer is named in the summary and the run is flagged, never passed off as clean.
- **Stable ids** (`AZ-<licence>`) for diffing between scheduled runs: schedule the same list daily and you have licence-lapse alerts on your subcontractors.

### Pricing

Pay per delivered row. Filtered-out rows cost nothing. A lookup that finds nothing charges nothing beyond the start fee.

### Need more states?

The same tool covers 20 states in one query, with a per-state coverage table so you know before you buy which boards publish a phone or an email: https://apify.com/wellbuilt\_zythem/us-contractor-license-lookup

### Data source

Arizona Registrar of Contractors (AZ ROC). A public regulatory register published so that anyone can verify a licence; contact details are the business contacts the board publishes for that purpose.

# Actor input Schema

## `mode` (type: `string`):

Lookup verifies a list of names or licence numbers. Export downloads a whole state and trade. Full detail reads the CSLB licence page for each California licence number you pass: bond, workers' compensation carrier and policy, classifications, entity type and today's status. It is the only mode that answers for a licence that is expired, inactive, cancelled or not in the register at all, because the bulk California file publishes active licences only.

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

One per line. A licence number matches exactly; a name matches any Arizona licensee or business containing it.

## `trades` (type: `array`):

Leave empty for every trade the Arizona board licenses.

## `onlyActive` (type: `boolean`):

Drop expired, suspended and out-of-business licences.

## `onlyWithPhone` (type: `boolean`):

For calling lists.

## `onlyExpiringSoon` (type: `boolean`):

The renewal window. Who sells bonds, insurance or continuing education wants exactly these.

## `expiringWithinDays` (type: `integer`):

Keep only licences that expire in the next N days (1 to 365). The renewal list: whoever sells bonds, insurance or continuing education calls these first. Leave empty for no window. Overrides the fixed 60-day "expiring soon" switch when set.

## `issuedWithinDays` (type: `integer`):

Keep only licences first issued in the last N days (1 to 365): newly licensed contractors, which is a new business needing suppliers, software, a truck and insurance. Uses the board's issue date; boards that do not publish one return nothing here rather than a guess.

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

0 for no limit.

## Actor input object example

```json
{
  "mode": "lookup",
  "queries": [
    "Johnson Electric",
    "17001"
  ],
  "trades": [],
  "onlyActive": false,
  "onlyWithPhone": false,
  "onlyExpiringSoon": false,
  "maxResults": 0
}
```

# Actor output Schema

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

One row per licence matched (lookup), per licence in the state and trade (export), or per licence number checked (California full detail, which adds bond, workers' compensation and classifications). Normalised across states: status, expiry, days to expiry, phone, address. A California number that is not in the register comes back with found: false and is not charged.

## `runSummary` (type: `string`):

Rows read and delivered per state, which registries failed to respond, and how many rows were charged.

# 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": [
        "Johnson Electric",
        "17001"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("wellbuilt_zythem/arizona-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 = { "queries": [
        "Johnson Electric",
        "17001",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("wellbuilt_zythem/arizona-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 '{
  "queries": [
    "Johnson Electric",
    "17001"
  ]
}' |
apify call wellbuilt_zythem/arizona-contractor-license-lookup --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,wellbuilt_zythem/arizona-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/zjZRGTigpzdO3gfpG/builds/fzjiOhqfd4cqsfx4p/openapi.json
