# Contractor License Leads (Texas) (`leadforge-data/contractor-license-leads`) Actor

Texas contractor licenses (TDLR public data) with a new-licenses-only mode. Business-focused; phone and street address off by default.

- **URL**: https://apify.com/leadforge-data/contractor-license-leads.md
- **Developed by:** [LeadForge Data](https://apify.com/leadforge-data) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## 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

## Contractor License Leads (Texas)

Returns Texas contractor license records (license number, license type, business/owner name, city, ZIP, county, derived status and expiration date) from the Texas Department of Licensing and Regulation (TDLR) public open data on data.texas.gov, with an optional mode that returns only licenses new since your previous run.

> **Florida is temporarily unavailable.** The Florida DBPR source currently refuses requests from the Apify cloud. `FL` is accepted in `states` but is skipped with a warning and returns no records.

### When to use

- You need a list of licensed Texas contractors of specific TDLR license types (default: A/C, Electrical, Appliance Installation, Electrical Sign contractors).
- You want only active (non-expired) Texas licenses — the default.
- You run on a schedule and want only Texas licenses that appeared since the last run (`newOnly: true`).

### When not to use

- You need Florida or any state other than Texas (Florida currently returns nothing; other states are not supported).
- You need the license **issue date** for Texas — the source does not publish it.
- You need to verify one specific license authoritatively — check the agency's own lookup site; this actor scans a whole dataset.
- You need email addresses (not output) or phone/street address without opting in.
- You need a consumer report or eligibility decision (see FCRA notice below).

### Example input

```json
{ "states": ["TX"], "txLicenseTypes": ["Electrical Contractor"], "activeOnly": true, "maxItems": 50 }
```

### Example output (one record per license)

```json
{
  "state": "TX",
  "licenseNumber": "100",
  "licenseType": "Appliance Installation Contractor",
  "licenseTypeCode": "RAIC",
  "name": "OBY'S APPLIANCE INSTALLATION, INC",
  "businessName": "OBY'S APPLIANCE INSTALLATION, INC",
  "address": null,
  "city": "AUSTIN",
  "addrState": "TX",
  "zip": "78757",
  "county": "TRAVIS",
  "phone": null,
  "isSoleProprietor": false,
  "nameRole": "license owner",
  "status": "Active",
  "firstSeenDate": "2026-10-26",
  "expirationDate": "2027-02-28",
  "isNewSinceLastRun": null,
  "source": "https://data.texas.gov/d/7358-krk7"
}
```

### Input parameters

| Parameter | Type | Default | Allowed values / units | Meaning |
|---|---|---|---|---|
| `states` | array of strings | `["TX"]` | `"TX"`; `"FL"` accepted but skipped (unavailable) | States to collect |
| `txLicenseTypes` | array of strings | 4 contractor types (see above) | Exact TDLR `license_type` names, case-sensitive | Texas license types to include |
| `activeOnly` | boolean | `true` | `true` / `false` | `true` drops expired licenses. TX status is derived from `expirationDate` (before today = Expired, dropped; missing = Unknown, kept) |
| `newOnly` | boolean | `false` | `true` / `false` | TX only: return only licenses not in the previous run's snapshot. First run per `txLicenseTypes` set returns 0 TX records (baseline) |
| `maxItems` | integer | `200` | 1–100000 records | Total output cap across states |
| `includePhone` | boolean | `false` | `true` / `false` | Opt-in TX business phone; otherwise `phone` is null |
| `includePersonalNames` | boolean | `false` | `true` / `false` | Opt-in. When `false`, `name` is null for records with `isSoleProprietor=true`; `businessName` is unchanged |
| `includeStreetAddress` | boolean | `false` | `true` / `false` | Opt-in street address; otherwise `address` is null. City/ZIP/county always included |
| `txAppToken` | string (secret) | none | data.texas.gov app token | Optional; only reduces throttling |
| `sinceDate` | string | none | `YYYY-MM-DD` | FL only (original license date); ignored for TX. No effect while FL is unavailable |
| `excludeQualifiedBusiness` | boolean | `true` | `true` / `false` | FL only (unavailable): skip Qualified Business records without license numbers |

### Output fields

| Field | Type | Meaning |
|---|---|---|
| `state` | string | `"TX"` |
| `licenseNumber` | string | TDLR license number |
| `licenseType` / `licenseTypeCode` | string | TDLR license type name / subtype code |
| `name` | string or null | License owner name. Null for inferred sole proprietors unless `includePersonalNames`; non-null names may still be individuals |
| `businessName` | string or null | Business name as published |
| `address` | string or null | Street address; null unless `includeStreetAddress` |
| `city`, `addrState`, `zip`, `county` | string | Business location |
| `phone` | string or null | Null unless `includePhone` |
| `isSoleProprietor` | boolean | Rule-based guess, not official (see note below) |
| `nameRole` | string | `"license owner"` |
| `status` | string | `Active`, `Expired` or `Unknown`, derived from `expirationDate` on the run date (not an official status) |
| `firstSeenDate` | string `YYYY-MM-DD` | Date this actor's snapshot first saw the license — **NOT the issue date** |
| `expirationDate` | string `YYYY-MM-DD` or null | License expiration date |
| `isNewSinceLastRun` | boolean or null | `true` in `newOnly` mode, otherwise null |
| `source` | string | Source dataset URL |
| `issueDate` | string | FL only; absent for TX |

### Limitations — please read

- **Texas only; Florida is temporarily unavailable.**
- **No completeness or accuracy guarantee.** Data comes from public records exactly as the agency publishes them, and may be delayed, incomplete or contain errors. Verify important records with the agency.
- **`firstSeenDate` is not the license issue date.** Texas' public data does not publish an issue date; `firstSeenDate` is when this actor's snapshot first saw the license (baseline-run records get the baseline date). "New" means new compared with your previous run, not newly issued.
- TX `status` is derived from the expiration date; the dataset has no status column, so suspended/revoked licenses that are not yet expired may show as Active.
- `newOnly` keeps its snapshot in the named key-value store `contractor-license-leads-state` in your own Apify account; delete it to reset.
- The whole selected TX dataset (~36,000 rows for the default types) is downloaded each run, paced at ≥1 s per page, even when `maxItems` is small.
- If the source is unavailable or its format changes, the run fails with an error instead of returning empty results; the TX snapshot is never overwritten by a failed or >10%-smaller fetch.
- If the agency changes its dataset, the actor may need updating.

### Pricing

Currently free to use (Apify platform usage applies per Apify's terms). Any future pricing change will be announced in advance per Apify Store rules.

### Sources

- Texas: Source: Texas Department of Licensing and Regulation, via data.texas.gov dataset 7358-krk7. This actor only reads this publicly published API and does not log in to anything.

### Data & compliance notice

**Data & compliance notice.** All data is compiled from public government records (Texas TDLR) and is provided "as is" without warranty of accuracy or completeness. Some records may identify individual sole proprietors. You are solely responsible for how you use this data, including compliance with CAN-SPAM, the TCPA and the National Do Not Call Registry, state telemarketing laws, and privacy laws such as the CCPA/CPRA. Do not use this data for unsolicited robocalls/texts, harassment, or any purpose prohibited by law or by the source agency. This actor is not affiliated with or endorsed by any government agency.

Not for use as a consumer report or for credit, employment, insurance, or housing eligibility decisions under the FCRA.

**Note on `isSoleProprietor`:** this flag is a rule-based inference (TX: owner name equals business name and contains no entity suffix such as INC/LLC/CORP; FL: no DBA name), not an official classification. It may have false positives and false negatives. Because `includePersonalNames=false` hides `name` only for records flagged as sole proprietors, detection may miss some individuals, and their names can still appear in `name`.

# Actor input Schema

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

Array of strings. Allowed values: "TX" (Texas TDLR licenses). "FL" is accepted but Florida is temporarily unavailable: it is skipped with a warning and returns no records. Default: \["TX"].

## `sinceDate` (type: `string`):

String, date in YYYY-MM-DD format. Optional, no default. Florida only (filters on the original license date). Ignored for Texas, because the Texas source has no issue date; use newOnly for Texas. Because Florida is unavailable, this currently has no effect.

## `activeOnly` (type: `boolean`):

Boolean. Default: true. When true, expired licenses are dropped. Texas: status is derived from expirationDate (expirationDate earlier than today = Expired, dropped; missing expirationDate = Unknown, kept). Florida (unavailable): keeps only DBPR status Current. Set false to also return expired Texas licenses.

## `txLicenseTypes` (type: `array`):

Array of strings. Texas only. Exact TDLR license_type names from data.texas.gov dataset 7358-krk7 (case-sensitive). Default: \["A/C Contractor", "Electrical Contractor", "Appliance Installation Contractor", "Electrical Sign Contractor"].

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

Integer, number of output records. Range 1 to 100000. Default: 200. Total across all states; the run stops when it is reached.

## `newOnly` (type: `boolean`):

Boolean. Default: false. Texas only. When true, returns only licenses not present in the snapshot saved by the previous run (named key-value store 'contractor-license-leads-state' in the caller's Apify account, one snapshot per txLicenseTypes set). The first run with a given txLicenseTypes set only creates the baseline and returns 0 Texas records. firstSeenDate is the date this actor first saw the license, NOT the license issue date.

## `excludeQualifiedBusiness` (type: `boolean`):

Boolean. Default: true. Florida only (currently unavailable). When true, skips Qualified Business (QB) records, which DBPR publishes without a license number. When false, they are included and sorted after individual licensees.

## `includePhone` (type: `boolean`):

Boolean. Default: false. Texas only. When true, outputs the TDLR business_telephone in the phone field; when false, phone is null. For sole proprietors this is often a personal number. The caller is responsible for TCPA/DNC/CCPA compliance.

## `includePersonalNames` (type: `boolean`):

Boolean. Default: false. When false, the name field is null for records flagged isSoleProprietor=true (likely individuals); businessName is unchanged. When true, the license owner name is always output. Sole-proprietor detection is rule-based and may miss some individuals, so some non-null names may still be personal names.

## `includeStreetAddress` (type: `boolean`):

Boolean. Default: false. When true, outputs street address lines in the address field; when false, address is null. City, state, ZIP and county are always output. Street addresses of individual licensees are often residential. The caller is responsible for privacy-law compliance.

## `txAppToken` (type: `string`):

String, secret. Optional, no default. A free data.texas.gov (Socrata) app token; only reduces throttling and does not change results. Leave empty if you do not have one.

## Actor input object example

```json
{
  "states": [
    "TX"
  ],
  "activeOnly": true,
  "txLicenseTypes": [
    "A/C Contractor",
    "Electrical Contractor",
    "Appliance Installation Contractor",
    "Electrical Sign Contractor"
  ],
  "maxItems": 200,
  "newOnly": false,
  "excludeQualifiedBusiness": true,
  "includePhone": false,
  "includePersonalNames": false,
  "includeStreetAddress": false
}
```

# Actor output Schema

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

No description

# 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 = {
    "states": [
        "TX"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("leadforge-data/contractor-license-leads").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 = { "states": ["TX"] }

# Run the Actor and wait for it to finish
run = client.actor("leadforge-data/contractor-license-leads").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 '{
  "states": [
    "TX"
  ]
}' |
apify call leadforge-data/contractor-license-leads --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,leadforge-data/contractor-license-leads"
        }
    }
}
```

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/Z0Vgy1urro3CBzqpo/builds/y9nHrs4diOAT6ES3i/openapi.json
