# CT Business Registry - Companies, Filings & Officers (`j0401/ct-business-registry`) Actor

Connecticut's business register (1.3M companies) with its filing history, officers, registered agents and name changes: status, business type, NAICS, formation place, ownership flags and the dissolution reason, plus every filed document and the people behind the business - on one exact id.

- **URL**: https://apify.com/j0401/ct-business-registry.md
- **Developed by:** [Wenhao Yang](https://apify.com/j0401) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.06 / 1,000 ct business records

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?

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

## CT Business Registry - Companies, Filings & Officers

Connecticut's **business register** and the Secretary of the State's **filing history, officers and registered agents** for it, on one exact key.

Every business in Connecticut has a business id. That id is the same in the register and in each of the four satellite files, so a company's current record, every document it ever filed, the people behind it, its registered agent and its name-change trail all line up exactly - no name matching, no fuzzy joins.

### Low cost

**From $0.00006 per record** Pay-per-event: you are charged per record delivered, and nothing for the query.

### What you get

| Corpus | Rows | Row is |
|---|---|---|
| `entities` | **1,297,469** | one registered business |
| `filings` | **10,065,884** | one filed document |
| `principals` | **1,788,417** | one officer / director of a business |
| `agents` | **1,312,992** | one registered-agent appointment |
| `nameChanges` | **96,505** | one recorded name change |

#### The register (`entities`)

- **Status** - 26 exact values: `Active` (460,739), `Forfeited` (357,172), `Dissolved` (319,109), `Withdrawn` (53,797), `Revoked` (46,479), `Cancelled`, `Merged`, `Expired Reservation`, `Rejected`, `Expired` and the pending-conversion states.
- **Sub-status** - the administrative machinery the status alone hides: `Annual report past due`, `Admin Dissolution Initiated`, `Ready for dissolution`, `Ready for Forfeiture`, `No Agent`, `Fraudulent Filing Complaint Sent`.
- **Business type** - 22 named values (`LLC` 837,641, `Stock` 344,334, `Non-Stock` 65,346, `Limited Partnership`, `Religious`, `LLP`, `Statutory Trust`, `B Corp`, `Cemetery`, `Bank Stock`), plus a blank on 15,071 rows where the source records none.
- **Why a business was administratively dissolved** - the stated reason, where the source gives one.
- **Formation** - the place of formation and the state / country of formation, alongside `citizenship` (domestic or foreign).
- **NAICS industry code** - populated on 612,858 businesses.
- **Five ownership flags** - woman-owned, veteran-owned, minority-owned, owned by a person with disabilities, LGBTQI-owned; 162,257 businesses carry at least one.
- **Authorized shares**, the annual-report due date, the dissolution date, the registration date, and the full business address with email.
- The **account number** - Connecticut's own public business number, distinct from the internal id.

#### The filing history (`filings`)

Every document: `Annual Report` (6,143,433), `Certificate of Organization` (755,621), `Notice of Intent to Dissolve/Revoke` (509,720), `Certificate of Dissolution/Revocation` (446,706), `Certificate of Dissolution` (323,756), `Agent Address Change` (315,490), `Certificate of Incorporation` (304,913), `Organization and First Report` (265,380), `Interim Notice` (156,494), `Amend Name` (80,163) and more - each with its category, the report year, the organizer or incorporator where the source records one, and the volume / page of the original book filing.

#### The people (`principals`)

**1,788,417 officers and directors** across 1,088,133 businesses - name, the office held (`Officer` 168,393, `Director` 70,845, `Officer;Director` 51,190), and both a business and a residence address. The office is blank on 1,497,989 rows where the source records no designation. A large corporation's file runs to **130 principals**; the whole board comes back in one profile.

#### The agents (`agents`)

**1,312,992 agent appointments** - whether the agent is an `Individual` (997,238), a `Business` (233,854) or the `Secretary of the State` (80,346, the default when a business has none), with the agent's phone, email, mailing address and business address. Each appointment also carries the state's own account number where the source records one.

#### The name changes (`nameChanges`)

**96,505 recorded changes** - the old name, the new name and the date, back to 1859. The trail a current-name-only lookup loses entirely.

### Modes

- **`rows`** (default) - records matching your filters: search the register by name, status, type, city, NAICS or formation place.
- **`aggregate`** - one count row per group. Roll the register up by status, business type, state, formation place, citizenship or state of formation; the filings by type, category or report year; the people by designation.
- **`profile`** - one business id in, the register row plus its filings, officers, agents and name changes out, up to your `maxResults` budget.

### Inputs

Filters follow the corpus you pick - the register takes `name`, `status`, `businessType`, `city`, `state`, `zip`, `naics`, `formationPlace`, `activeOnly` and a registration-date window; the filings take `filingType`, `reportYear` and a date window; the people take `personName`, `designation`, `agentType` and `phone`; the name changes take `oldName`, `newName` and a date window.

A filter that belongs to another corpus is rejected outright rather than silently ignored - so a query you narrowed never comes back unnarrowed.

### Example inputs

**Active LLCs in Hartford**

```json
{ "corpus": "entities", "status": "Active", "businessType": "LLC",
  "city": "Hartford", "maxResults": 200 }
```

**Everything Connecticut holds on one business**

```json
{ "mode": "profile", "businessId": "001t000000yGOECAA4", "maxResults": 500 }
```

**Every officer named in a business**

```json
{ "corpus": "principals", "businessId": "001t000000WnNjxAAF", "maxResults": 200 }
```

**Businesses that changed their name this year**

```json
{ "corpus": "nameChanges", "changedFrom": "2026-01-01", "maxResults": 500 }
```

**How many businesses by status**

```json
{ "mode": "aggregate", "corpus": "entities", "groupBy": "status" }
```

### Notes on the data

- **The principals and agents files are one-to-many.** A business can have up to 130 principals, and 1,788,417 principal rows cover 1,088,133 businesses. A profile of a large company returns its whole board, and you are billed per person returned - so set `maxResults` to what you actually want for a very large business.
- **Duplicate appointment rows are removed on output.** Both files are reloaded wholesale each night, so the same person can reappear as several rows that differ only in the loader's timestamp. Identical rows are emitted once, so the same officer is never charged twice.
- **The source mixes codes and names for the same place.** `CT` (801,167) and `Connecticut` (250,363) are the same formation place; `DE` and `DELAWARE` likewise. Filter `formationPlace` by substring to catch both spellings.
- **The sub-status is usually empty.** 1,172,026 of 1,297,469 businesses have none - it is only set while an administrative action is in flight.
- **162,499 filings carry no filing date.** They are kept, not dropped, and they sort last rather than surfacing as the newest filings.
- **16% of ZIP codes are ZIP+4** (`06033-4617`). The ZIP filter matches the 5-digit prefix, so both forms are returned.

### Output

One JSON record per row, with the same key set whichever corpus produced it - so the rows load cleanly into a table or a dataframe without a schema union step.

**Pay-per-event** - you are charged per record delivered (`entity-record`), never for the query itself. The run stops cleanly if you set a spend limit on your Apify account.

# Actor input Schema

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

rows = records matching your filters (default). aggregate = one count row per group (see groupBy). profile = one business's registry row plus its filings, officers, agents and name changes - requires businessId.

## `corpus` (type: `string`):

entities = the register (1,297,469 businesses, default). filings = filed documents (10,065,884). principals = officers and directors (1,788,417). agents = registered agents (1,312,992). nameChanges = recorded name changes (96,505). Filters below apply to the corpus you pick.

## `businessId` (type: `string`):

Exact Connecticut business id, e.g. '001t000000yGOECAA4'. The one key that ties a business to its filings, officers, agents and name changes.

## `name` (type: `string`):

Business name substring, e.g. 'TRANSPORT', 'HOLDINGS'. Blank = any. (entities corpus)

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

Exact registration status (26 values). Active 460,739, Forfeited 357,172, Dissolved 319,109, Withdrawn 53,797, Revoked 46,479. Blank = any. (entities corpus)

## `businessType` (type: `string`):

Exact business type (22 named values, plus a blank on 15,071 rows the source leaves unclassified). LLC 837,641, Stock 344,334, Non-Stock 65,346, Limited Partnership 19,039. Blank = any. (entities corpus)

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

Business-address city substring, e.g. 'Hartford', 'Stamford'. Blank = any. (entities corpus)

## `state` (type: `string`):

Two-letter business-address state, e.g. 'CT'. Blank = any. (entities corpus)

## `zip` (type: `string`):

Business-address ZIP - matches the 5-digit prefix, so both '06033' and the ZIP+4 form '06033-4617' are returned (16% of rows store ZIP+4). Digits and dashes only. Blank = any. (entities corpus)

## `naics` (type: `string`):

Exact NAICS industry code (populated on 612,858 businesses). Blank = any. (entities corpus)

## `formationPlace` (type: `string`):

Where the business was formed, substring match - the source mixes codes and names ('CT' 801,167 and 'Connecticut' 250,363 are the same place). Blank = any. (entities corpus)

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

Restrict to status = Active (460,739 businesses). Off = any status. (entities corpus)

## `registeredFrom` (type: `string`):

Businesses registered on or after this date (YYYY-MM-DD). Rows with no registration date are kept, not dropped. Blank = any. (entities corpus)

## `registeredTo` (type: `string`):

Businesses registered on or before this date (YYYY-MM-DD). Blank = any. (entities corpus)

## `filingType` (type: `string`):

Filing type substring, e.g. 'Annual Report' (6,143,433), 'Certificate of Organization' (755,621), 'Certificate of Dissolution'. Blank = any. (filings corpus)

## `reportYear` (type: `string`):

Exact report year on the filing, e.g. '2020'. Blank = any. (filings corpus)

## `filedFrom` (type: `string`):

Filings dated on or after this (YYYY-MM-DD). Blank = any. (filings corpus)

## `filedTo` (type: `string`):

Filings dated on or before this (YYYY-MM-DD). Blank = any. (filings corpus)

## `personName` (type: `string`):

Officer / director / agent name substring, e.g. 'SMITH'. Blank = any. (principals and agents corpora)

## `designation` (type: `string`):

The office held, substring match - 'Officer' (168,393), 'Director' (70,845), 'Officer;Director' (51,190). Blank on 1,497,989 rows where the source records no office. Blank = any. (principals corpus)

## `agentType` (type: `string`):

Exact registered-agent type. Individual 997,238, Business 233,854, Secretary of the State 80,346. Blank = any. (agents corpus)

## `phone` (type: `string`):

Exact agent phone number, digits only, e.g. '2032466712'. Blank = any. (agents corpus)

## `oldName` (type: `string`):

The business name before the change, substring match. Blank = any. (nameChanges corpus)

## `newName` (type: `string`):

The business name after the change, substring match. Blank = any. (nameChanges corpus)

## `changedFrom` (type: `string`):

Name changes recorded on or after this date (YYYY-MM-DD). Blank = any. (nameChanges corpus)

## `changedTo` (type: `string`):

Name changes recorded on or before this date (YYYY-MM-DD). Blank = any. (nameChanges corpus)

## `groupBy` (type: `string`):

Which dimension to aggregate over (mode=aggregate). The first six belong to entities, the next three to filings, designation/principalType to principals and agentType to agents. Blank = a sensible default for the selected table - do not leave it set when switching corpus.

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

Cap the number of records pushed in rows / profile mode (0 = up to ~10k per run; each record is metered individually, so there is no per-run charge cap). Aggregate mode returns every group.

## Actor input object example

```json
{
  "mode": "rows",
  "corpus": "entities",
  "businessId": "",
  "name": "",
  "status": "",
  "businessType": "",
  "city": "",
  "state": "",
  "zip": "",
  "naics": "",
  "formationPlace": "",
  "activeOnly": false,
  "registeredFrom": "",
  "registeredTo": "",
  "filingType": "",
  "reportYear": "",
  "filedFrom": "",
  "filedTo": "",
  "personName": "",
  "designation": "",
  "agentType": "",
  "phone": "",
  "oldName": "",
  "newName": "",
  "changedFrom": "",
  "changedTo": "",
  "groupBy": "",
  "maxResults": 50
}
```

# Actor output Schema

## `recordsUrl` (type: `string`):

Connecticut business records, filings, officers, agents or aggregates - as JSON

## `datasetUrl` (type: `string`):

No description

## `runUrl` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("j0401/ct-business-registry").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("j0401/ct-business-registry").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 j0401/ct-business-registry --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,j0401/ct-business-registry"
        }
    }
}
```

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/OHSqLPKsFhhqsrvdD/builds/Pqs8Vg3dE1bBgke7E/openapi.json
