# Oklahoma Contractor License Lookup & List Scraper (CIB) (`scrapebench/oklahoma-contractor-license-lookup`) Actor

Every Oklahoma electrical, mechanical and plumbing licence from the Construction Industries Board: contractors, journeymen, apprentices and inspectors, with licence type, number, status and city. Export a trade or check a name.

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

## Pricing

$0.004 / trade licence

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

## Oklahoma Contractor License Lookup & List Scraper (CIB)

### Pain points

- The CIB licence search answers one trade or one name at a time on a single long web page, with no export button and no download (checked 2026-10-30).
- The search page has no licence-type, status or city filter, so finding the active plumbing contractors in Tulsa means reading every plumbing licence in the state.
- A licence number is not unique: the same number can belong to several people across trades (one 2026-10-30 search for 003019 returned five licences), so a number alone can point at the wrong person.

### What we solve

- Returns any CIB trade as a table: 264,976 licences across the nine trades on October 30, 2026, filterable by licence class (Contractor, Journeyman, Apprentice, Inspector), status and city.
- Exports include the 3,274 licences the board's trade lists leave out (it shows one licence per person per trade, so a contractor's journeyman licence in the same trade is missing there), read from each active contractor's own licence page.
- Checks a person's name or a licence number live against the board's own search and returns every matching licence with its type, status and city.
- Links every row to the board's own page for that person, so two people sharing a licence number stay two rows.

### Summary

Oklahoma Construction Industries Board trade licences in one dataset: electrical, mechanical and plumbing contractors and journeymen, their apprentices, and the board's building, home, electrical, mechanical and plumbing inspectors. Each row has the licence holder's name, city, licence type, licence class, licence number, status and citation flag. The CIB licenses individuals, not companies, and publishes no address, phone or email, so this is a verification and list product, not a contact list. On October 30, 2026 the stored copy held 264,976 licences: 43,895 active, 6,224 of them active contractor licences (2,436 mechanical, 2,094 electrical, 1,694 plumbing). Lookups search the board live; exports read a stored copy. Pay only per licence returned.

### Who it's for

- General contractors and property managers checking that an electrician, plumber or HVAC tech holds an active Oklahoma licence
- Staffing agencies and trade schools tracking licensed journeymen and apprentices by trade and city
- Compliance and procurement teams verifying subcontractor licences in bulk
- Suppliers sizing the licensed trade workforce in an Oklahoma city

### How to use

This actor does two jobs. Run it, then collect results from the run's dataset (export to JSON/CSV/Excel, or pull via the Apify API).

**Get a list (export):** no names, just filters; returns the whole matching list.

```json
{
  "categories": [
    "plumbing"
  ],
  "license_class": "Contractor",
  "status": "Active",
  "maxResults": 500
}
```

**Check specific firms (lookup):** put company names or licence numbers in `mode`, `queries`; **Inputs** below says how each is matched.

```json
{
  "mode": "lookup",
  "queries": [
    "Smith, John",
    "00196169"
  ],
  "maxResults": 20
}
```

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

### What you get

One row per record:

| Field | Description |
|---|---|
| `name` | Licence holder, as the board prints it: LAST, FIRST MIDDLE (always a person) |
| `listing_id` | Licence number exactly as the board prints it, leading zeros included; not unique on its own |
| `extras.license_type` | Licence type, e.g. Electrical Contractor License, Plumbing Journeyman License, Mechanical Apprentice Registration |
| `extras.license_class` | Contractor, Journeyman, Apprentice or Inspector |
| `extras.status` | Licence status: Active, Expired, Inactive, Pending - CE Hours, Tax, Withdrawn, Denied, Deceased, Completed |
| `extras.citation` | Yes or No: whether the board shows a citation on the licence |
| `category` | Trade: Electrical, Mechanical, Plumbing, their Apprentice trades, or an inspector trade |
| `city` | The holder's city as the board lists it (no street, state or ZIP is published) |
| `source_url` | The board's own verification page for this licence |

Sample:

```json
{
  "listing_id": "00192177",
  "name": "ALDER, ALEX A",
  "city": "WILBURTON",
  "country": "US",
  "category": "Plumbing",
  "categories": [
    "Plumbing"
  ],
  "source": "live",
  "source_url": "https://okcibv7prod.glsuite.us/GLSuiteWeb/Clients/OKCIB/Public/LicenseeSearch/Posting.aspx?EntityID=1693095&LicenseID=1436877",
  "extras": {
    "license_type": "Plumbing Journeyman License",
    "license_class": "Journeyman",
    "status": "Active",
    "citation": "No"
  }
}
```

### Inputs

| Field | Required | Type | Default | Description |
|---|---|---|---|---|
| `mode` | no | string | `"auto"` | export: no names, just filters; returns the whole matching list. lookup / verify: put person names (matched if contained in the person name) or licence numbers (exact) in 'queries'. auto picks the mode for you. |
| `query` | no | string | — | A person's name (or listing number) to look up live. Kept alongside 'queries' for saved tasks. |
| `queries` | no | array | `[]` | A person's name (or listing number) to look up live. Several values in one run; combined with 'query'. |
| `license_class` | no | string | — | Only listings in this license_class. Kept alongside 'license_classes' for saved tasks. |
| `license_classes` | no | array | `[]` | Only listings in this license_class. Several values in one run; combined with 'license_class'. |
| `status` | no | string | — | Only listings in this status. Kept alongside 'statuses' for saved tasks. |
| `statuses` | no | array | `[]` | Only listings in this status. Several values in one run; combined with 'status'. |
| `city` | no | string | — | Only listings in this city. Kept alongside 'cities' for saved tasks. |
| `cities` | no | array | `[]` | Only listings in this city. Several values in one run; combined with 'city'. |
| `categories` | no | array | `[]` | Only rows from this trade (one or more). Available: building-inspector, electrical, electrical-apprentice, home-inspector, mechanical, mechanical-apprentice, plumbing, plumbing-apprentice, plumbing-inspector. |
| `maxResults` | no | integer | `500` | Per query in lookup mode; per run in export mode. |
| `proxyConfiguration` | no | object | `{"useApifyProxy": false}` | Used only for live lookups; exports read the stored snapshot. |

### Pricing (Pay Per Event)

You pay per result (`dataset-item`) — **no charge for empty runs**. Example: **1000 trade licences** at *$0.004/result* ≈ **$4.00**.

Notices (unknown trade, no match, stale data) are free. Apify platform usage is billed separately per your plan.

### Use cases

- Subcontractor checks: confirm a list of electricians' licences are Active before they start work.
- Workforce counts: active journeyman plumbers in Oklahoma City, or apprentices by trade.
- Licence audits: every Mechanical Contractor licence in Pending - CE Hours or Inactive status.
- Verification by number: a licence number returns every person who holds it, with type and status.

### Why this actor

- A whole trade in one run, not one long page per search.
- Filters the board's search lacks: licence class, status and city, each taking a list.
- Name and number lookups run live in all nine trades (the board's own search shows one licence per person unless a trade is chosen), with the stored copy as a fallback.
- Pay per licence; notices are free.

### Limitations & updates

Covers the licences the Oklahoma Construction Industries Board publishes in its trade licence search: electrical, mechanical, plumbing, their apprentices and the board's inspectors. No roofing (a separate registry) and no general contractors (Oklahoma has no state licence). Name and city only: no address, phone, email or expiry date. Exports read a stored copy; lookups are live.

### FAQ

**Where does the data come from?**

The Oklahoma Construction Industries Board's public licence search (the CIB License Verification site). Lookups search it live; exports read a stored copy of every trade.

**Is there a phone, address or email?**

No. The board licenses individuals and publishes only the holder's name and city, on the search and on each licence's verification page. No public CIB source carries a street address, phone or email for these licences (checked 2026-10-30).

**What about roofing or general contractors?**

Oklahoma has no state general-contractor licence. Roofing contractors register separately with the CIB; for them (with phone and address) use the Oklahoma roofing contractor actor in this suite.

**Which trades are covered?**

The nine options of the board's search: electrical, mechanical, plumbing, electrical-apprentice, mechanical-apprentice, plumbing-apprentice, building-inspector, home-inspector and plumbing-inspector. Put one or more in Trade; leave it empty for all.

**How do I get only active contractors?**

Set license_class to Contractor and status to Active. license_class takes Contractor, Journeyman, Apprentice or Inspector; status takes the board's own words (Active, Expired, Inactive, …).

**How do I look up a person?**

Put a last name, "Last, First" or "First Last" in queries. The board matches the last name exactly and the first name as a prefix, and needs at least three letters of the last name. The board's own search shows one licence per person unless a trade is chosen, so each name is searched in all nine trades: about 40 seconds per name. If the live search cannot answer, the stored copy is searched instead and the run says so in a free notice.

**Can I verify a licence number?**

Yes. Put the number in queries as the board prints it, leading zeros included, and set mode to lookup. The board gives a person one number for all their licences (one holder had five under 00158663), and old numbers repeat across people, so a number usually returns several licences; check the name and licence type. In mode auto or verify, a number with several licences returns one free notice instead of guessing; add license_class (e.g. Contractor) to narrow it.

**How current is it?**

Lookups are live. Exports read a copy taken on October 30, 2026; the run log states its date, and a copy older than 45 days returns one free notice saying so.

**How am I charged?**

One event per licence returned. Notices are free.

### 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 Oklahoma Contractor License Lookup & List Scraper (CIB)](https://scrapebench.dev/guides/how-to-oklahoma-contractor-license-lookup/)
- **Use case:** [Oklahoma Active Plumbing Contractors (CIB)](https://scrapebench.dev/use-cases/oklahoma-active-plumbing-contractors/)

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/oklahoma-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 active plumbing contractors licensed by the Oklahoma Construction Industries Board."

That is Trade plumbing, license_class Contractor, status Active. Keep maxResults small on a first call. Runs started this way bill exactly like any other run.

### Data & lawful use

This actor collects publicly available information that the Oklahoma Construction Industries Board (CIB) publishes for public
lookup — licence records, business listings and the contact details professionals list there.
Some of it identifies individuals (sole proprietors, licence holders, agents), so treat any
names, phone numbers and emails in your results as personal data.

When you run this actor, you decide what is collected and what it is used for, so you are the
controller of that data and we act only as your processor (Apify Standard Actor Contract).
You need a lawful basis for your use, must honour opt-out and deletion requests, and must
follow the marketing rules that apply to you (CAN-SPAM, TCPA, GDPR, CCPA and similar).
Don't use the output for unsolicited bulk messaging, for screening covered by the FCRA, or
for anything the source's own terms forbid.

Your results are stored in your own Apify account. We don't keep a copy of your results and
don't sell or share them.

### Disclaimer

This is an independent tool. It is not affiliated with, endorsed by or sponsored by
the Oklahoma Construction Industries Board (CIB). Names and marks are used only to describe the data source. Records are
provided as published by the source and may be out of date or incomplete. For anything
consequential (hiring, a permit, a legal decision), confirm the record with the issuing
agency. You are responsible for making sure your use complies with applicable law and the
source's terms.

### Need help?

Open an issue on this actor's **Issues** tab and we'll respond there. Bug reports, missing
fields and feature requests are all welcome. Guides and examples: [scrapebench.dev](https://scrapebench.dev).

If you are a person named in this data and want your record removed from our copy, email
apify-help@scrapebench.dev; the source agency remains the official record.

Your run may be used to improve our services. If something looks off, or you want this actor to fit your use better, please share your run data with us: [Apify Console → Settings → Security → Share run data with developers](https://console.apify.com/settings/security). It lets us see exactly what went wrong and keep improving the actor.

# Actor input Schema

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

export: no names, just filters; returns the whole matching list. lookup / verify: put person names (matched if contained in the person name) or licence numbers (exact) in 'queries'. auto picks the mode for you.

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

A person's name (or listing number) to look up live. Kept alongside 'queries' for saved tasks.

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

A person's name (or listing number) to look up live. Several values in one run; combined with 'query'.

## `license_class` (type: `string`):

Only listings in this license_class. Kept alongside 'license_classes' for saved tasks.

## `license_classes` (type: `array`):

Only listings in this license_class. Several values in one run; combined with 'license_class'.

## `status` (type: `string`):

Only listings in this status. Kept alongside 'statuses' for saved tasks.

## `statuses` (type: `array`):

Only listings in this status. Several values in one run; combined with 'status'.

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

Only listings in this city. Kept alongside 'cities' for saved tasks.

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

Only listings in this city. Several values in one run; combined with 'city'.

## `categories` (type: `array`):

Only rows from this trade (one or more). Available: building-inspector, electrical, electrical-apprentice, home-inspector, mechanical, mechanical-apprentice, plumbing, plumbing-apprentice, plumbing-inspector.

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

Per query in lookup mode; per run in export mode.

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

Used only for live lookups; exports read the stored snapshot.

## Actor input object example

```json
{
  "mode": "auto",
  "queries": [],
  "license_classes": [],
  "statuses": [],
  "cities": [],
  "categories": [],
  "maxResults": 500,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

One row per business listing; notices are free.

# 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("scrapebench/oklahoma-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("scrapebench/oklahoma-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 '{}' |
apify call scrapebench/oklahoma-contractor-license-lookup --silent --output-dataset

```

## MCP server setup

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