# Chicago Business Licenses Scraper (`automation-lab/chicago-business-licenses`) Actor

Search and export official City of Chicago business license records by business, license number, status, type, address, geography, and issue or expiration dates.

- **URL**: https://apify.com/automation-lab/chicago-business-licenses.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.92 / 1,000 item 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

## Chicago Business Licenses Scraper

Search, filter, and export **Chicago business licenses** from the official City of Chicago open-data portal.

The Actor returns normalized business identity, license type and number, official status, activities, address, geography, issue dates, and expiration dates. Use it for repeatable compliance checks, local-market research, prospecting, and scheduled change monitoring.

### What does Chicago Business Licenses Scraper do?

The Actor queries official Socrata datasets published by the City of Chicago.

It supports:

- full-text search across City records;
- partial legal-name and DBA-name matching;
- exact license number and official status-code lookup;
- license type, address, ZIP code, and ward filters;
- issued-date and expiration-date windows;
- all-records and current-active source datasets;
- deterministic pagination up to the requested limit;
- JSON, CSV, Excel, XML, and other Apify dataset exports.

Each output item is one official license row. No browser, login, or proxy is required.

### Who is it for?

#### Compliance and risk teams

Verify a business's public license record, status, class, and expiration date before onboarding or during periodic reviews.

#### Sales and market-research teams

Build location-level lists by license type, ZIP code, ward, neighborhood, or business activity.

#### Data analysts

Load normalized Chicago license rows into spreadsheets, warehouses, dashboards, or entity-resolution pipelines.

#### Operations teams

Schedule a date-window query and compare datasets between runs to find newly issued, renewed, or changed records.

### Why use the Actor instead of downloading manually?

The City portal is useful for one-off browsing, but recurring exports require repeatable query construction, pagination, normalization, and integration work.

This Actor provides:

1. a stable input contract;
2. server-side filtering at the official source;
3. normalized camelCase output;
4. bounded transient retries;
5. Apify scheduling and integrations;
6. a provenance URL and retrieval timestamp on every row.

The Actor does not enrich or infer license status. It preserves the City's published values.

### Getting started

1. Open the Actor in Apify Console.
2. Enter a business name or another filter.
3. Choose **All business license records** or **Current active licenses**.
4. Set the maximum number of rows.
5. Click **Start**.
6. Open the **License records** dataset.
7. Export or connect the results to your workflow.

A useful first run is:

```json
{
  "businessName": "Walgreens",
  "sourceDataset": "currentActive",
  "maxItems": 25
}
```

### Input parameters

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `query` | string | — | Full-text search across the official dataset. |
| `businessName` | string | — | Partial, case-insensitive legal or DBA name. |
| `licenseNumber` | string | — | Exact Chicago license number. |
| `licenseStatus` | string | — | Exact official status code, such as `AAI`. |
| `licenseType` | string | — | Partial match against the license description. |
| `address` | string | — | Partial licensed-address match. |
| `zipCode` | string | — | Exact ZIP code. |
| `ward` | string | — | Exact ward number. |
| `issuedFrom` | date | — | Earliest issue date, inclusive. |
| `issuedTo` | date | — | Latest issue date, inclusive. |
| `expiresFrom` | date | — | Earliest expiration date, inclusive. |
| `expiresTo` | date | — | Latest expiration date, inclusive. |
| `sourceDataset` | string | `all` | `all` or `currentActive`. |
| `maxItems` | integer | `100` | Maximum saved rows, from 1 to 50,000. |

All supplied filters are combined. For example, a license type plus ZIP code returns only rows matching both.

### Choose the right official dataset

Use `currentActive` when you need the City's current-active subset and want a smaller search surface.

Use `all` when you need historical applications, non-current rows, status filtering, or issue-date monitoring.

The source is updated by the City. A scheduled Actor run reflects what the official endpoint returns at run time.

### Output fields

Important fields include:

| Group | Fields |
| --- | --- |
| Identity | `legalName`, `doingBusinessAsName`, `accountNumber`, `siteNumber` |
| License | `licenseId`, `licenseNumber`, `licenseCode`, `licenseType`, `licenseStatus` |
| Activity | `businessActivityIds`, `businessActivities`, `applicationType` |
| Address | `address`, `city`, `state`, `zipCode` |
| Geography | `ward`, `precinct`, `policeDistrict`, `communityAreaName`, `neighborhood` |
| Dates | `dateIssued`, `licenseStartDate`, `expirationDate`, `statusChangeDate` |
| Provenance | `sourceRecordId`, `sourceDataset`, `sourceUrl`, `retrievedAt` |

Fields can be `null` when the City does not publish a value for a row.

### Output example

This abbreviated example reflects real current Actor behavior:

```json
{
  "sourceRecordId": "1069844-20260516",
  "licenseNumber": "1069844",
  "legalName": "WALGREEN CO.",
  "doingBusinessAsName": "Walgreens #5926",
  "licenseType": "Retail Food Establishment",
  "licenseStatus": "AAI",
  "businessActivities": "Retail Sales of Perishable Foods",
  "address": "4385 S ARCHER AVE 1ST",
  "zipCode": "60632",
  "ward": "12",
  "dateIssued": "2026-05-13T00:00:00.000",
  "expirationDate": "2028-05-15T00:00:00.000",
  "sourceDataset": "currentActive",
  "sourceUrl": "https://data.cityofchicago.org/resource/uupf-x98q.json"
}
```

### Search and filtering examples

#### Look up one license number

```json
{
  "licenseNumber": "1069844",
  "sourceDataset": "all",
  "maxItems": 10
}
```

#### Build a local license-type list

```json
{
  "licenseType": "Limited Business License",
  "zipCode": "60640",
  "sourceDataset": "currentActive",
  "maxItems": 500
}
```

#### Collect a new-issuance window

```json
{
  "issuedFrom": "2026-08-01",
  "issuedTo": "2026-08-30",
  "sourceDataset": "all",
  "maxItems": 5000
}
```

### How much does it cost to export Chicago business licenses?

The Actor uses pay-per-event pricing:

- one `start` event is charged once per run;
- one `item` event is charged for each saved license row;
- no charge is made for rejected, duplicate, or empty rows.

The current price is **$0.005 per run** plus a tiered item event. The item price is **$0.009864 per record at BRONZE**, with lower rates on higher Apify tiers.

Examples at the BRONZE rate:

- 1 record: approximately **$0.014864** including the start event;
- 10 records: approximately **$0.10364** including the start event;
- 100 records: approximately **$0.99140** including the start event.

Apify applies the tier associated with your plan, and Console displays the authoritative estimate before a run.

### Scheduling license monitoring

A useful recurring workflow is:

1. choose the `all` dataset;
2. set an issue-date or expiration-date window;
3. schedule the Actor daily, weekly, or monthly;
4. send each dataset to cloud storage or a webhook;
5. compare `sourceRecordId`, `licenseStatus`, and date fields with the previous run.

The Actor returns snapshots. It does not itself retain prior-run state, send alerts, or label changes.

### Export and integration patterns

Apify datasets can be downloaded as JSON, CSV, Excel, XML, or RSS.

Common workflows include:

- Google Sheets for review queues;
- webhooks for compliance pipelines;
- Make or Zapier for no-code automation;
- Python or JavaScript for entity matching;
- BigQuery, Snowflake, or object storage for historical snapshots.

Use `sourceRecordId` as the primary source-row key. A license number can occur across terms or applications, so do not assume it uniquely identifies every historical row.

### Run through the Apify API with cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~chicago-business-licenses/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "businessName": "Walgreens",
    "sourceDataset": "currentActive",
    "maxItems": 25
  }'
```

Keep API tokens in environment variables or a secret manager.

### Run through the Apify API with JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/chicago-business-licenses').call({
  licenseType: 'Limited Business License',
  zipCode: '60640',
  sourceDataset: 'currentActive',
  maxItems: 100,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Run through the Apify API with Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/chicago-business-licenses').call(run_input={
    'issuedFrom': '2026-08-01',
    'issuedTo': '2026-08-30',
    'sourceDataset': 'all',
    'maxItems': 100,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### Use with Apify MCP

Add the Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/chicago-business-licenses"
```

#### Claude Desktop

Add this server to Claude Desktop's MCP configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/chicago-business-licenses"
    }
  }
}
```

#### Cursor

Use the same JSON server entry in Cursor's MCP settings.

#### VS Code

Add the same HTTP MCP server URL through your VS Code MCP extension or workspace MCP configuration.

Example prompts:

- “Find current active Chicago business licenses matching Walgreens.”
- “Export Limited Business License rows in ZIP code 60640.”
- “Collect licenses issued during August 2026 and summarize license types.”

### Reliability and retries

The Actor requests the official API directly and fetches up to 1,000 rows per page.

It retries transient network, HTTP 429, and selected 5xx failures up to three times with backoff.

It does not retry deterministic validation errors or unsupported inputs.

If the official API remains unavailable after retries, the run fails instead of returning a misleading partial success.

### Limits and data freshness

- The maximum input limit is 50,000 rows per run.
- Full-text search behavior is controlled by Socrata.
- Official status codes are returned as published, not translated.
- Historical rows may share a license number.
- Address and coordinates may be missing or differ from mailing information.
- Date fields reflect City records and are not legal advice.
- Dataset updates are controlled by the City of Chicago.

For very broad exports, use filters and schedule multiple bounded windows rather than repeatedly downloading unchanged records.

### Troubleshooting

#### Why did the run return zero rows?

Remove filters one at a time and verify the selected dataset. A historical record may not be present in `currentActive`, and official status codes must match exactly.

#### Why was my date input rejected?

Use `YYYY-MM-DD`, and ensure the start date is not after the end date.

#### Why do several rows have the same license number?

The all-records dataset can include different applications, sites, or license terms. Use `sourceRecordId` for row-level deduplication.

#### Why did the run fail with a City API error?

Check the run log and retry later if the official open-data service is unavailable. The Actor already performs bounded transient retries.

### Responsible use and legality

The source is a public City of Chicago open-data service. Review the City's dataset documentation and terms before use.

Use records for lawful purposes. Apply appropriate retention, security, fairness, and human-review controls when data contributes to compliance, onboarding, credit, employment, or enforcement decisions.

A public license row does not prove that a business is suitable, unsafe, compliant in every respect, or legally authorized outside the published license scope.

### Related Automation Lab Actors

- [NPPES NPI Registry Provider Search](https://apify.com/automation-lab/npi-registry-provider-search) for US healthcare-provider identity and license fields.
- [Texas Pharmacy License Lookup](https://apify.com/automation-lab/texas-pharmacy-license-lookup) for Texas pharmacy credential verification.
- [Chicago Food Inspections Scraper](https://apify.com/automation-lab/chicago-food-inspections-scraper) when food-safety inspection results, rather than business licenses, are the buyer job.

These Actors cover different official sources and should not be treated as equivalent registries.

### FAQ

#### Does the Actor require a Chicago data account?

No. It uses anonymous public endpoints.

#### Does it require an Apify Proxy?

No. The implementation uses direct HTTP and does not expose a proxy fallback.

#### Can I export every Chicago license?

You can request up to 50,000 rows per run. Use bounded date or geography filters for larger recurring workflows.

#### Does the Actor monitor changes automatically?

Apify schedules can run it repeatedly. Comparing datasets or sending alerts must be implemented in your downstream workflow.

#### Are inactive licenses included?

Choose `all` for historical and non-current records. Choose `currentActive` for the City's current-active subset.

#### Can I search by business activity?

Use `query` for full-text source search. Dedicated structured filters cover business name, license type, number, status, address, geography, and dates.

#### Is this legal advice or an official verification certificate?

No. The Actor exports public source records and provenance. Verify material decisions with the responsible City department.

# Actor input Schema

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

Full-text search across the official dataset, for example a business name, street, or activity.

## `businessName` (type: `string`):

Case-insensitive partial match against legal and doing-business-as names.

## `licenseNumber` (type: `string`):

Exact City of Chicago license number.

## `licenseStatus` (type: `string`):

Exact official status code, such as AAI. Use the current active dataset if you only need active licenses.

## `licenseType` (type: `string`):

Case-insensitive partial match against the license description.

## `address` (type: `string`):

Case-insensitive partial match against the licensed address.

## `zipCode` (type: `string`):

Exact ZIP code filter.

## `ward` (type: `string`):

Exact Chicago ward number.

## `issuedFrom` (type: `string`):

Include licenses issued on or after this date (YYYY-MM-DD).

## `issuedTo` (type: `string`):

Include licenses issued on or before this date (YYYY-MM-DD).

## `expiresFrom` (type: `string`):

Include licenses expiring on or after this date (YYYY-MM-DD).

## `expiresTo` (type: `string`):

Include licenses expiring on or before this date (YYYY-MM-DD).

## `sourceDataset` (type: `string`):

Search all historical/current rows or only the City's current-active subset.

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

Stop after saving this many matching license rows.

## Actor input object example

```json
{
  "businessName": "Walgreens",
  "sourceDataset": "currentActive",
  "maxItems": 20
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset containing normalized Chicago business license records.

# 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 = {
    "businessName": "Walgreens",
    "sourceDataset": "currentActive",
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/chicago-business-licenses").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 = {
    "businessName": "Walgreens",
    "sourceDataset": "currentActive",
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/chicago-business-licenses").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 '{
  "businessName": "Walgreens",
  "sourceDataset": "currentActive",
  "maxItems": 20
}' |
apify call automation-lab/chicago-business-licenses --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/chicago-business-licenses"
        }
    }
}

```

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/uTUaLGcm9GzWUxyi6/builds/OwcxHOe04kPRrumfB/openapi.json
