# Tennessee Contractor Licenses Scraper (`automation-lab/tennessee-contractor-license-lookup`) Actor

Search official Tennessee contractor licenses and export organizations, license numbers, status, expiration, classifications, locations, and source record IDs.

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

## Pricing

from $4.15 / 1,000 result extracteds

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?

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

## Tennessee Contractor Licenses Scraper

Search official **Tennessee contractor licenses** and export contractor organizations,
license numbers, status, expiration dates, classifications, locations, and stable
source record IDs.

This Actor queries the Tennessee Department of Commerce and Insurance Commerce
Verify Public Search. It is designed for recurring vendor verification, procurement
due diligence, compliance refreshes, and one-time contractor research.

### What does this Actor do?

Provide one or more organization names or contractor license numbers.
The Actor searches each term against the official contractor program, keeps
organization records, removes duplicate source records, and writes normalized rows
to the default Apify dataset.

By default, every accepted result is enriched from its official detail page.
That adds the original licensure date, classifications, monetary limit, and location
when those fields are public for the record.

The source is restricted to the Tennessee **Contractors and Ltd Licensed Plumbers**
board/program. Results from unrelated professional boards are not mixed into the
output.

### Who is it for?

- Procurement teams checking a Tennessee contractor before onboarding.
- Compliance teams refreshing license standing and expiration dates.
- General contractors reviewing subcontractor credentials.
- Insurers and risk teams collecting public qualification evidence.
- Analysts building an auditable contractor-license dataset.
- Developers integrating official license checks into internal workflows.

### Why use it?

The public portal is useful for a person checking one record, but recurring checks
need consistent structured output. This Actor provides:

- Batch input for up to 100 names or license numbers.
- Pagination across official search matches.
- Stable deduplication using the Commerce Verify source record ID.
- Optional exact status filtering.
- Detail enrichment without browser automation.
- A typed dataset ready for JSON, CSV, Excel, APIs, webhooks, or schedules.
- Direct links back to every official source record.

### What Tennessee contractor license data is extracted?

| Field | Meaning |
| --- | --- |
| `sourceRecordId` | Stable Commerce Verify credential record ID. |
| `organizationName` | Public contractor organization name. |
| `entityType` | Source entity type; emitted records are organizations. |
| `licenseNumber` | Tennessee contractor license number. |
| `licenseType` | Public license type. |
| `board` | Tennessee board or program. |
| `status` | Current source status, such as Active or Expired. |
| `expirationDate` | Public expiration date, or `null` when absent. |
| `originalLicensureDate` | Original licensure date from details, or `null`. |
| `city` | Public city, or `null`. |
| `state` | Public state, or `null`. |
| `postalCode` | Public ZIP code, or `null`. |
| `county` | Public county, or `null`. |
| `classifications` | Public classification/modifier codes. |
| `monetaryLimit` | Public monetary-limit text, or `null`. |
| `matchedSearchTerms` | Inputs associated with the source record. |
| `sourceUrl` | Direct official Commerce Verify detail URL. |
| `scrapedAt` | UTC collection timestamp. |

### How to get started

1. Open the Actor input page.
2. Add one or more organization names or license numbers to **Search terms**.
3. Optionally enter an exact status such as `Active`.
4. Keep **Include license details** enabled for classifications and licensure dates.
5. Choose a maximum number of records.
6. Click **Start**.
7. Open the Dataset tab to download JSON, CSV, Excel, XML, or another supported format.

A useful first input is:

```json
{
  "searchTerms": ["53194"],
  "includeDetails": true,
  "maxItems": 1
}
```

### Input parameters

#### `searchTerms`

Required array of 1–100 organization names or license numbers.
Each value must contain 2–255 characters. Terms are searched independently.
Duplicate source records are merged.

#### `status`

Optional exact, case-insensitive status filter.
For example, use `Active` when a workflow should retain only currently active
records. Leave it blank to receive every matching status.

#### `includeDetails`

Defaults to `true`.
When enabled, the Actor requests each official detail record and adds original
licensure date, classification codes, monetary limit, and richer location fields.
Disable it for a faster list-only check when those fields are not needed.

#### `maxItems`

Defaults to 100 and supports 1–10,000 unique records.
The limit applies across all search terms after source-ID deduplication.

### Output example

This shortened example comes from the real public license `53194`:

```json
{
  "sourceRecordId": "C45565",
  "organizationName": "FORT SMITH STRUCTURAL INC.",
  "entityType": "Organization",
  "licenseNumber": "53194",
  "licenseType": "Contractor",
  "board": "Contractors and Ltd Licensed Plumbers",
  "status": "Active",
  "expirationDate": "09/30/2028",
  "originalLicensureDate": "02/01/2005",
  "city": "FORT SMITH",
  "state": "Arkansas",
  "postalCode": "72918",
  "county": "Sebastian",
  "classifications": ["BC-21"],
  "monetaryLimit": "Monetary Limit - Value: $3,000,000.00",
  "matchedSearchTerms": ["53194"],
  "sourceUrl": "https://search.cloud.commerce.tn.gov/search/C45565/detail",
  "scrapedAt": "2026-09-12T00:00:00.000Z"
}
```

Dates are preserved in the official display format.
A nullable field means the source did not publish that value for the record.

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

The Actor uses pay-per-event pricing:

- A one-time `start` event is charged once per run.
- A `result` event is charged only for each useful contractor license row saved.
- Searches with no accepted records do not incur result-event charges.
- Detail enrichment has no separate event charge.

On the Bronze tier, the start event is **$0.005 per run** and each saved result is
**$0.006912**. Example Bronze totals are approximately:

| Saved records | Approximate total |
| ---: | ---: |
| 1 | $0.011912 |
| 10 | $0.07412 |
| 100 | $0.69620 |

Apify subscription tiers can have different event prices.
The Console shows the applicable price before a run.

### Search tips

- Use a complete license number for the narrowest lookup.
- Use a distinctive full business name instead of a generic word.
- Set `status` to `Active` for active-vendor refresh jobs.
- Keep the source URL and source record ID in downstream audit tables.
- Schedule the same input and compare records by `sourceRecordId` and key fields.
- Start with a small `maxItems` while designing a new workflow.

### Recurring vendor verification workflow

Create one scheduled Actor task containing the vendor names or license numbers you
need to check. Export each run to your database or spreadsheet. Join current and
previous rows by `sourceRecordId`, then flag changes in:

- `status`
- `expirationDate`
- `classifications`
- `monetaryLimit`
- organization or location fields

The Actor returns snapshots. It does not itself send change alerts or compare runs.
Use Apify schedules, webhooks, integrations, or your own data pipeline for those
steps.

### Integrations

Dataset results can be sent to:

- Google Sheets through an Apify integration.
- Make or Zapier through a webhook workflow.
- Slack or email through a downstream automation.
- Amazon S3, BigQuery, or a data warehouse through an API client.
- Internal procurement and compliance services through the dataset API.

For repeat checks, create an Actor task, save the input, and attach a schedule.

### Run with the Apify API

Replace `APIFY_TOKEN` with your token.

#### cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~tennessee-contractor-license-lookup/runs?token=APIFY_TOKEN&waitForFinish=120" \
  -H "Content-Type: application/json" \
  -d '{"searchTerms":["53194"],"maxItems":1}'
```

#### JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/tennessee-contractor-license-lookup').call({
  searchTerms: ['53194'],
  includeDetails: true,
  maxItems: 1,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("APIFY_TOKEN")
run = client.actor("automation-lab/tennessee-contractor-license-lookup").call(
    run_input={"searchTerms": ["53194"], "includeDetails": True, "maxItems": 1}
)
items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items)
```

### Use with MCP and AI assistants

Add the actor-scoped Apify MCP server to Claude Code:

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

For **Claude Desktop**, **Cursor**, or **VS Code**, add this MCP JSON configuration:

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

Example prompts:

- “Use the Tennessee Contractor Licenses Scraper to verify license 53194.”
- “Check these Tennessee contractor license numbers and return only active records.”
- “Export the expiration dates and source URLs for these contractor organizations.”

### Limits and failure behavior

The Actor searches one Tennessee Commerce Verify contractor board/program.
It does not cover every Tennessee professional license, local occupational permits,
or contractor records from another state.

Search is provided by the source. Broad words may return related matches, so use
specific names or license numbers when precision matters.

The Actor retries temporary network, HTTP 429, and server failures up to three times.
It refreshes the anonymous source token after HTTP 401. Invalid input and stable
source errors fail the run rather than silently producing a misleading empty dataset.

The source can omit expiration, classification, monetary-limit, or location values.
Those fields are returned as `null` or an empty array instead of being guessed.

### Responsible use and legality

This Actor accesses public professional-credential information from an official
Tennessee government search service. Use the data for lawful verification,
research, and compliance purposes. Follow applicable terms, privacy rules, and
retention requirements.

A public license record is not a legal opinion, endorsement, or guarantee of work
quality. For consequential decisions, open the included official source URL and
confirm the record with the responsible Tennessee authority.

### Troubleshooting

#### Why did a name return several organizations?

The official search can match words across public record fields. Use a more complete
business name, an exact license number, a smaller limit, or downstream review.

#### Why is an expiration date null?

The source did not publish an expiration value for that credential. Enable detail
enrichment, then verify the linked official record if the field remains absent.

#### Why did an Active filter return no rows?

The filter is exact and case-insensitive. The matching source record may use another
status, may be expired, or the term may not identify a contractor organization.
Run once without `status` to inspect the source status.

#### Are no-result searches charged per result?

No. The result event is charged only after a valid organization license row is saved.
The one-time start event still applies.

### FAQ

#### Does this Actor verify individual tradespeople?

No. It intentionally emits contractor organization records from the selected
contractor board/program.

#### Can I search multiple vendors in one run?

Yes. Add up to 100 names or license numbers to `searchTerms`.

#### Does it monitor changes automatically?

The Actor returns a current snapshot. Save it as an Apify task, schedule recurring
runs, and compare datasets or use a downstream automation for change alerts.

#### Can I disable detail requests?

Yes. Set `includeDetails` to `false`. Core organization, license, status, expiration,
location, source ID, and source URL remain available when published in search rows.

#### Is this an official Tennessee service?

No. This is an independent Apify Actor that reads public records from the official
Tennessee Commerce Verify source and links each result back to that source.

### Related automation-lab Actors

- [California Contractor License Lookup](https://apify.com/automation-lab/california-contractor-license-lookup-v2) for California CSLB records.
- [North Carolina Contractor License Lookup](https://apify.com/automation-lab/north-carolina-contractor-license-lookup-scraper) for North Carolina general-contractor records.
- [Contractor License Verification Scraper](https://apify.com/automation-lab/contractor-license-verification-scraper) for supported multi-source contractor checks.

These are separate Actors with source-specific fields and inputs.

# Actor input Schema

## `searchTerms` (type: `array`):

One or more Tennessee contractor business names or license numbers. Each value is searched independently and duplicate records are merged.

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

Optional exact status filter, for example Active or Expired. Leave blank to return every matching status.

## `includeDetails` (type: `boolean`):

Fetch each official detail record to add original licensure date, classifications, and monetary limit.

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

Maximum number of unique contractor organization records saved across all search terms.

## Actor input object example

```json
{
  "searchTerms": [
    "FORT SMITH STRUCTURAL"
  ],
  "status": "",
  "includeDetails": true,
  "maxItems": 10
}
```

# Actor output Schema

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

Default dataset items using the overview table view, available through the Apify Dataset API.

# 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 = {
    "searchTerms": [
        "FORT SMITH STRUCTURAL"
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/tennessee-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 = {
    "searchTerms": ["FORT SMITH STRUCTURAL"],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/tennessee-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 '{
  "searchTerms": [
    "FORT SMITH STRUCTURAL"
  ],
  "maxItems": 10
}' |
apify call automation-lab/tennessee-contractor-license-lookup --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/tennessee-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/NMDfgcRWjBu0N9I7o/builds/kUZwWYsUb4XjDvHw9/openapi.json
