# Chicago & Cook County Contractor License Lookup & Leads Scraper (`scrapebench/chicago-contractor-license-lookup`) Actor

Contractors licensed by the City of Chicago Department of Buildings, registered with the Cook County Department of Building and Zoning (52 specialities) and with the City of Evanston (25 trades), with street address and phone. Export or look up.

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

## Pricing

$0.002 / contractor record

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

## Chicago & Cook County Contractor License Lookup & Leads Scraper

### Pain points

- Illinois has no statewide general contractor licence; the City of Chicago licenses the contractors who work in Chicago, so a Chicago contractor list has to come from the city.
- The Department of Buildings' Licensed Contractors pages show 25 rows at a time in an on-screen table with no download button (checked 2026-11-06).
- Its search box answers one name or licence number at a time.
- Cook County keeps a separate register of the contractors allowed to pull permits in unincorporated Cook County, on its own search, one speciality per page.

### What we solve

- Three local registers in one actor, each row tagged with its locality: Chicago (the city's licences), Cook County (the County's registered contractors) and Evanston (the city's contractor registrations).
- Every licence on the Department of Buildings' roster in one dataset: 17,420 licences (10,788 active, 6,632 inactive) on November 6, 2026.
- One clean table: company, licence number, licence type and class, Active or Inactive, licence expiry, insurance or bond expiry, street, city, state, ZIP and phone.
- Filter by licence type (General Contractor Class A to E, Electrical, Low Voltage, Plumbing, Mason Class A to C, Elevator Mechanic), status and expiry date; look up names or licence numbers live against the city's own search.

### Summary

Chicago contractor licences from the City of Chicago Department of Buildings: the general, electrical, plumbing, mason and elevator contractors licensed to work in Chicago, current and recently expired or inactivated. Each row has the company, the licence number, the licence type and class, the city's own Active or Inactive flag, the licence expiry, the insurance or bond expiry where the city lists one, a street address split into street, city, state and ZIP, and a phone. On November 6, 2026 the roster held 17,420 licences: a phone on 17,386, a full address on 17,396; 6,519 Class E and 3,208 Class D general contractors, 3,111 electrical and 1,303 plumbing contractors; 6,282 firms list a Chicago address. Cook County: the Department of Building and Zoning's registered contractors, in 52 specialities (general with and without trades, plumbing, electrical and its sub-trades, HVAC, roofing, concrete, masonry, fence, sewer, water, well, septic, sign, paving and more), one row per contractor and address carrying every speciality it is registered for, with a one-line street address (the County prints no comma between street and city, so the city stays in the street line), state, ZIP, phone, fax and the registration date; the County publishes no licence number, status or expiry. On November 6, 2026 its Plumbing page listed 450 contractors (a phone on 449) and General - With Trades 542 (a phone on 541). Home-owner registrations are left out. Evanston: the City of Evanston's contractor registrations on its Accela Citizen Access licensee search, 25 trades under the City's own names (GC RESIDENTIAL, GC COMMERCIAL, PLUMBING, ELECTRICAL, HVAC, ROOFING, MASONRY, CONCRETE, SEWER, TREE, WINDOWS AND SIDING and more; GC OWNER, home owners, left out), each with the registration number, street address, expiry and an Active / Expired status derived from it; each delivered row's own page adds the phone, e-mail and contact name. Exports read a stored copy of each register; lookups search all three live. Pay only per licence returned.

### Who it's for

- Building-material suppliers, distributors and equipment rental firms selling to contractors working in Chicago and Cook County
- Insurers, bonding agents, lenders and payroll providers reaching licensed Chicago contractors
- Property managers, owners and general contractors checking a contractor's Chicago licence, class and expiry
- Market researchers sizing the Chicago construction trades

### 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
{
  "licenseTypes": [
    "General Contractor (Class E)",
    "General Contractor (Class D)"
  ],
  "statuses": [
    "Active"
  ],
  "maxResults": 1000
}
```

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

```json
{
  "mode": "lookup",
  "queries": [
    "Plumbing",
    "TGC04300"
  ],
  "maxResults": 20
}
```

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

### What you get

One row per record:

| Field | Description |
|---|---|
| `license_number` | Chicago: the city's licence number (TGC… general, ECC… electrical, BC/SBC… plumbing, MC… mason, BEVC… elevator); Evanston: its registration number (09LICR-0001; state numbers such as 055-… for plumbers); listing_id holds the same. Cook County publishes none |
| `business_name` | Company as the register lists it; name holds the same |
| `license_type` | Chicago: licence type and class as the city prints it, e.g. General Contractor (Class E). Cook County: the speciality, e.g. Plumbing (classifications lists every one) |
| `status` | Chicago: Active or Inactive, from the city's own 'License Inactive' flag. Cook County: Registered (listed in its current search). Evanston: Active or Expired, derived from the expiry |
| `extras.registered` | Cook County: the registration date the County prints (YYYY-MM-DD) |
| `extras.fax` | Cook County: fax, where listed |
| `expiration_date` | Licence expiry (YYYY-MM-DD) |
| `extras.insurance_expires` | Insurance or bond expiry (YYYY-MM-DD), where the city lists one (general and plumbing contractors) |
| `address` | Street as listed; city, address_state and zip_code hold the rest (the full line is in extras.address). Cook County's line has no comma before the city, so its city stays in this field |
| `phone` | Phone as printed |
| `phone_e164` | The same phone in +1XXXXXXXXXX form |
| `extras.locality` | The local licensing authority the row comes from: Chicago, Cook County or Evanston |
| `email` | Evanston: e-mail from the registration's own page, where the City has one |
| `source_url` | Chicago: the city's licensed-contractor list, tagged with the licence number and name. Cook County: the County's exact-name search for the contractor, tagged with its address (neither publishes a per-licence page) |

Sample:

```json
{
  "license_number": "TGC04300",
  "business_name": "\"D\" CONSTRUCTION, INC",
  "license_type": "General Contractor (Class A)",
  "classifications": [
    "General Contractor (Class A)"
  ],
  "status": "Active",
  "expiration_date": "2027-03-10",
  "address": "1488 SOUTH BROADWAY ROAD",
  "city": "COAL CITY",
  "address_state": "IL",
  "zip_code": "60416",
  "phone": "(815) 634-2555",
  "phone_e164": "+18156342555",
  "state": "IL",
  "source_url": "https://webapps1.chicago.gov/licensedcontractors/all#license-TGC04300-%22D%22%20CONSTRUCTION%2C%20INC",
  "extras": {
    "locality": "Chicago",
    "licence_type": "General Contractor (Class A)",
    "expires": "2027-03-10",
    "insurance_expires": "2027-06-01"
  }
}
```

### Inputs

| Field | Required | Type | Default | Description |
|---|---|---|---|---|
| `mode` | no | string | `"auto"` | export: no names, just filters; returns the whole matching list. lookup / verify: put company names (matched if contained in the company name) or licence numbers (exact) in 'queries'. auto picks the mode for you. |
| `query` | no | string | — | A business name (or listing number) to look up live. Kept alongside 'queries' for saved tasks. |
| `queries` | no | array | `[]` | A business name (or listing number) to look up live. Several values in one run; combined with 'query'. |
| `locality` | no | string | — | Only listings in this locality. Kept alongside 'localities' for saved tasks. |
| `localities` | no | array | `[]` | Only listings in this locality. Several values in one run; combined with 'locality'. |
| `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'. |
| `categories` | no | array | `[]` | Only rows from this licence type (one or more). Available: Above Ground Pool, C3, CARPENTRY, CONCRETE, Carpentry, Cell Tower Erector, Concrete, Construction Manager, Crane Operator, DEMOLITION, DRAIN LAYER, Damp Proofing, Demolition, Drywall, EIFS - Stucco - Plaster, ELECTRICAL, ELEVATOR, EXCAVATION, Electrical, Electrical - Audio Visual, Electrical - Fire Alarm, Electrical - Other, Electrical - Power & Lighting, Electrical - Security, Electrical - Sign, … (88 in all; an unknown name returns the full list, free). |
| `licenseTypes` | no | array | `[]` | Same filter as 'Licence type', under the name every state licence actor takes; the two lists are combined. |
| `expiresAfter` | no | string | — | Only licences expiring on or after this date (YYYY-MM-DD). Licences with no published expiry are left out when set. |
| `expiresBefore` | no | string | — | Only licences expiring on or before this date (YYYY-MM-DD): renewals coming due. |
| `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 license matches** at *$0.004/result* ≈ **$4.00**.

Notices (unknown licence type, no match, source unavailable) are free. Apify platform usage is billed separately per your plan.

### Use cases

- Sales lists: every active Class D or Class E general contractor licensed in Chicago, with street address and phone.
- Renewal and insurance campaigns: licences expiring before a date (1,561 active licences expire by January 31, 2027, as read on 2026-11-06).
- Subcontractor checks: confirm a licence number, its class and whether the city marks it inactive before work starts.
- Market sizing: count Chicago-licensed contractors by trade and class, and by where they are based.
- Suburban trade lists: Cook County's registered plumbing, HVAC, roofing or fence contractors with phone and address (Locality Cook County).

### Why this actor

- The whole roster in one dataset, every trade and both active and inactive licences, instead of 25 rows a page.
- A phone on 17,386 of 17,420 licences and a split street address on 17,396 (2026-11-06).
- Filters the city's pages lack: several licence types at once, status and expiry dates.
- Pay per licence; notices are free.

### Limitations & updates

Covers the City of Chicago Department of Buildings' contractor roster (17,420 licences on 2026-11-06), the Cook County Department of Building and Zoning's registered contractors and the City of Evanston's contractor registrations, not the rest of Illinois or other Cook County towns' own registers. Email on Evanston rows only. Cook County rows have no licence number or expiry and keep the city inside the street line. Evanston exports leave out registrations that expired more than 3 years ago; its phone and e-mail are read per delivered row, and rows not opened before the run's time runs out are counted in a free notice. Lists current and recently expired or inactivated licences, not the full history. A licence number the city re-issued appears once per firm. Exports come from a stored copy (its date is in the run log).

### FAQ

**Where does the data come from?**

Three registers. The City of Chicago Department of Buildings' Licensed Trade Contractors site (webapps1.chicago.gov/licensedcontractors), which the city updates daily; the Cook County Department of Building and Zoning's registered-contractor search (secure.cookcountyil.gov/BZ); and the City of Evanston's licensee search (aca-prod.accela.com/EVANSTON). Exports read a stored copy of each (the run log gives its date); lookups search all three live and fall back to the stored copy when one does not answer. Set Locality to Chicago, Cook County or Evanston for one of them.

**Does it cover all of Illinois?**

No. Illinois has no statewide general contractor licence: cities and counties license or register contractors, and the state licenses roofers and plumbers separately. This actor reads the City of Chicago's roster, Cook County's register (the contractors allowed to pull permits in unincorporated Cook County) and the City of Evanston's registrations. Many firms on both are based in the suburbs or out of state (6,282 Chicago licences list a Chicago address), because a local licence is about where the work is done.

**What is in a Cook County row?**

The contractor, a one-line address (street and city together, then state and ZIP), phone, fax, every speciality it is registered for and the registration date. The County publishes no licence number, status or expiry, so status reads Registered (listed in the current search). Home-owner registrations (people building their own house) are left out.

**What do Active and Inactive mean?**

They are Chicago's own 'License Inactive' flag. The roster lists current licences and recently expired or inactivated ones; a licence can be inactive before its expiry date, so filter on status rather than on the expiry. Cook County rows read Registered.

**Is there an email?**

On Evanston rows, where the City has one: each delivered Evanston registration's own page is opened for its phone and e-mail (3 of 4 sample pages had both on 2026-11-06; one had the placeholder phone 0000000000, which is dropped). Chicago and Cook County publish no email: Chicago gives the company, licence number and type, status, expiry dates, a street address and a phone; Cook County the contractor, address, phone and fax.

**How do I look up a firm or a licence number?**

Put company names or licence numbers in queries and set mode to lookup. Chicago and Cook County match a name that contains your text (Chicago also a licence number); Evanston matches a business name or registration number from its start. Up to 100 Chicago matches per query are read, and the answers are interleaved.

**How current is it?**

Exports come from a stored copy of the roster, refreshed when it is over 30 days old and the actor is in use; the run log states its date, and a copy older than 45 days adds a free notice saying so. Lookups read the city's current list.

**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 Chicago & Cook County Contractor License Lookup & Leads Scraper](https://scrapebench.dev/guides/how-to-chicago-contractor-license-lookup/)
- **Use case:** [Chicago Licensed Contractors (all trades, active)](https://scrapebench.dev/use-cases/chicago-licensed-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/chicago-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 Class A general contractors licensed in Chicago, with their phone numbers and licence expiry."

That is Licence type General Contractor (Class A) with status Active (386 licences on 2026-11-06). 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 City of Chicago Department of Buildings (DOB), the Cook County Department of Building and Zoning and the City of Evanston 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 City of Chicago Department of Buildings (DOB), the Cook County Department of Building and Zoning and the City of Evanston. 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.

If this actor saved you time, a short review on its Store page helps other buyers find it.

# Actor input Schema

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

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

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

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

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

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

## `locality` (type: `string`):

Only listings in this locality. Kept alongside 'localities' for saved tasks.

## `localities` (type: `array`):

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

## `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'.

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

Only rows from this licence type (one or more). Available: Above Ground Pool, C3, CARPENTRY, CONCRETE, Carpentry, Cell Tower Erector, Concrete, Construction Manager, Crane Operator, DEMOLITION, DRAIN LAYER, Damp Proofing, Demolition, Drywall, EIFS - Stucco - Plaster, ELECTRICAL, ELEVATOR, EXCAVATION, Electrical, Electrical - Audio Visual, Electrical - Fire Alarm, Electrical - Other, Electrical - Power & Lighting, Electrical - Security, Electrical - Sign, … (88 in all; an unknown name returns the full list, free).

## `licenseTypes` (type: `array`):

Same filter as 'Licence type', under the name every state licence actor takes; the two lists are combined.

## `expiresAfter` (type: `string`):

Only licences expiring on or after this date (YYYY-MM-DD). Licences with no published expiry are left out when set.

## `expiresBefore` (type: `string`):

Only licences expiring on or before this date (YYYY-MM-DD): renewals coming due.

## `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": [],
  "localities": [],
  "statuses": [],
  "categories": [],
  "licenseTypes": [],
  "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/chicago-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/chicago-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/chicago-contractor-license-lookup --silent --output-dataset

```

## MCP server setup

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