# PA Registered Businesses - Officers & Signatories (`j0401/pa-registered-businesses`) Actor

Pennsylvania registered-business register (public open data, 4.1M officer rows across 2.36M registrations): the officers and signatories of every registered PA entity - role (President / Governor / Treasurer / Secretary / Organizer / Member), registration type, address with county and creation date.

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

## Pricing

from $0.06 / 1,000 pa registered-business officer 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

## Pennsylvania Registered Businesses - Officers & Signatories

Pennsylvania publishes its **registered-business file** as open data - every entity registered with the Department of State, together with the **officers and signatories** named on each registration. This actor turns that file into a **charged-per-record search, filter and aggregate tool**: find a business or a person, filter by role or county, or aggregate the register.

**Built for:** sales and B2B lead-gen (who runs a company), KYC and diligence (who is behind an entity), and anyone who wants **the people on a PA registration** without paging a portal one name at a time.

### What it covers

**4,110,251 officer rows** across **2,360,829 registered entities**. Read the grain before quoting a number: **one row is one officer / signatory of a business, not one business** - the 4.1M rows average ~1.74 per registration (one filing runs to 160 officers). The value is the **person layer**.

Each row carries:

- the **role** (`party_type`) - President (**801,111**), Governor (**770,661**), Organizer (**404,232**), Treasurer (**376,285**), Secretary (**225,015**), Vice President (**199,718**), General Partner, Incorporator, Member (**42,221**), Owner (**17,642**), ...
- the **registration type** - Domestic Limited Liability Company (**1,633,573**, the source's exact string - try that, not LLC), Domestic Business Corporation (**1,479,469**), Domestic Nonprofit Corporation, Foreign Business Corporation (**361,273**), ...
- the entity's **address, city, state and county** (**Philadelphia 575,656** / Dauphin / Allegheny / Montgomery / ...) and the **creation date**
- the person's first / middle / last name and the filing number that ties the officers of one entity together

### The fine print that matters

Two quirks are handled for you. **Role casing is inconsistent in the source** - `Member` / `MEMBER` / `member`, `Owner` / `OWNER` / `owner`, `PARTNER` / `Partner` - so the role filter **folds case** (a bare equality match would silently miss two-thirds of some roles). And **`creationdate` carries the sentinel 1753-01-01** on some rows (a .NET zero-date); years before 1900 are blanked on output so a fake 1753 never surfaces, while the genuine - often very old - formation dates are kept.

Worth stating plainly: `party_type` is **blank on 969,859 rows** (~24% of the file). That is a real gap in the source, kept as blank rather than dropped or invented.

### Typical questions

- "Everyone registered as an officer of **a given company**."
- "Every entity a person is tied to, by name."
- "All **Presidents** / **Governors** / **Treasurers** in **Philadelphia County**."
- "Newly registered **Domestic Limited Liability Company** entities since a date."
- "Aggregate the register by **registration type**, **county** or **state**."

### Inputs

| Input | What it does |
|---|---|
| `mode` | `rows` (default) / `aggregate` |
| `businessName` / `filingNumber` | find the entity |
| `officerName` / `partyType` | find the person and their role |
| `registrationType` | entity type |
| `county` / `city` / `state` / `zip` | where |
| `createdFrom/To` | creation-date range |
| `groupBy` | aggregate over registration type / county / state |
| `maxResults` | cap records (default 50) |

**Default run = the 50 most recent registrations** - fast for the daily auto-test. For a targeted query add a filter; for a broad view use `aggregate`.

### Example inputs

**Everyone named on one registration** - `filingNumber` ties the officers of one filing together; a filing runs to as many officers as the entity named.

```json
{ "filingNumber": "0015854682" }
```

**Every entity one person is tied to** - `officerName` matches a first or last name, and `partyType` narrows it to a role.

```json
{ "officerName": "Vaughn", "partyType": "Organizer", "maxResults": 25 }
```

**New entities of one type in one county** - `registrationType` takes the source's exact string ("Domestic Limited Liability Company", not "LLC").

```json
{
  "registrationType": "Domestic Limited Liability Company",
  "county": "Philadelphia",
  "createdFrom": "2026-01-01",
  "maxResults": 25
}
```

**Where the register concentrates** - one count per registration type.

```json
{ "mode": "aggregate", "groupBy": "registrationType" }
```

### Low cost

**From $0.0001 per record, down to $0.00006 at Gold** - billed only for the rows you use, at the low end of the store. Cost scales with what you pull, not with the size of the register, and each record is metered individually.

What a thin scraper misses is the **grain and the casing**. This is not a business list - it is the **officer layer** of one, and quoting "4.1 million businesses" from it would be off by nearly 2; a filing number ties a company's officers back together. The **role column is inconsistently cased** (`MEMBER` / `member` / `Member` are one role), so a naive filter silently misses two-thirds of some roles, and the **creation date carries a 1753 sentinel** that sorts to the bottom of any date view. Normalizing the officer-vs-business grain, the role casing and the zero-date into a schema where a `businessName` / `partyType` / `county` query returns exactly the people you mean is the actual product. Every pull is integrity-checked against the register's known shape, so a degraded source fails loudly instead of returning bad rows.

### Example output

**One officer row** - `filingNumber=0015854682` returns one record per officer named on that registration:

```json
{
  "platform": "pa-registered-businesses",
  "source": "pa-dos-registered-businesses",
  "mode": "rows",
  "groupKey": "",
  "groupCount": "",
  "groupBy": "",
  "businessName": "Overrated Property Co.",
  "filingNumber": "0015854682",
  "registrationType": "Domestic Limited Liability Company",
  "creationDate": "2026-09-02",
  "partyType": "Organizer",
  "lastName": "Vaughn",
  "middleName": "",
  "firstName": "Derrick",
  "address1": "1012 Pembroke Ave",
  "address2": "",
  "city": "Lansdowne",
  "state": "PA",
  "zip": "19050-2723",
  "county": "Delaware",
  "countyCode": "23",
  "latitudeLongitude": "{'type': 'Point', 'coordinates': [-75.25687, 39.94372]}"
}
```

**`mode=aggregate`, `groupBy=registrationType`** - one row per group:

```
Domestic Limited Liability Company   1,633,573
Domestic Business Corporation        1,479,469
Foreign Business Corporation           361,273
```

### Source

- [Pennsylvania: Registered Businesses Current by County](https://data.pa.gov/Business-Industry/Registered-Businesses-in-PA-Current-by-County/xvd7-5r2c) - the Department of State's registered-business file with officers and signatories. Public open data. Records are the state's own published fields; not an endorsement of any business or person.

# Actor input Schema

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

rows = officer rows matching your filters (default). aggregate = one count row per group (see groupBy).

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

Registered business name substring, e.g. 'MACRO', 'TRUCKING'. Blank = any.

## `filingNumber` (type: `string`):

Exact registration (filing) number. One registration can return several officer rows.

## `officerName` (type: `string`):

Officer first or last name substring - find every entity a person is tied to. Blank = any.

## `partyType` (type: `string`):

Officer role, case-insensitive: President, Governor, Treasurer, Secretary, Organizer, Vice President, Member, ... Blank = any.

## `registrationType` (type: `string`):

Entity type substring: Domestic Limited Liability Company, Domestic Business Corporation, Foreign Nonprofit Corporation, ... Blank = any.

## `county` (type: `string`):

County name substring, e.g. 'Philadelphia', 'Allegheny'. Blank = any.

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

Business address city substring. Blank = any.

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

Two-letter state of the business address. Blank = any.

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

Zip code (prefix match). Blank = any.

## `createdFrom` (type: `string`):

Only registrations created on/after this date (YYYY-MM-DD). The newest are first.

## `createdTo` (type: `string`):

Only registrations created before this date (YYYY-MM-DD).

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

Which dimension to aggregate over. Role and city are filters, not rollups (too many distinct values).

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

Cap the number of records pushed in rows 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",
  "businessName": "",
  "filingNumber": "",
  "officerName": "",
  "partyType": "",
  "registrationType": "",
  "county": "",
  "city": "",
  "state": "",
  "zip": "",
  "createdFrom": "",
  "createdTo": "",
  "groupBy": "registrationType",
  "maxResults": 50
}
```

# Actor output Schema

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

Pennsylvania registered-business officer records 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/pa-registered-businesses").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/pa-registered-businesses").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/pa-registered-businesses --silent --output-dataset

```

## MCP server setup

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

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/uE8EaiNoc1TneK1we/builds/j59ZaGmy3wAaLunwb/openapi.json
