# California SOS Business Search Scraper (`muhammadafzal/sos-scraper`) Actor

Search California Secretary of State BizFile business entities by name or entity number and return normalized status, filing, agent, address, and risk signals.

- **URL**: https://apify.com/muhammadafzal/sos-scraper.md
- **Developed by:** [Muhammad Afzal](https://apify.com/muhammadafzal) (community)
- **Categories:** Automation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $8.00 / 1,000 california sos record returneds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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

## California SOS Business Search Scraper

Search the official California Secretary of State BizFile Online business registry by company name or California entity number. The actor returns compact, typed records for due diligence, KYB checks, registered-agent research, business-status monitoring, and AI-agent workflows.

### What it does

Use this actor when you need public California registry data for corporations, LLCs, LPs, and nonprofit entities. It opens the official search page in a browser session, then calls the registry's own same-origin JSON search request from that session so Imperva cookies remain consistent. It does not file documents, order certificates, download filing images, log in to an account, or bypass a CAPTCHA or anti-bot challenge.

The actor is designed for compliance teams, legal and due-diligence researchers, sales operations teams validating business names, journalists, and AI agents that need a small structured answer instead of a browser transcript.

### When to use it

Use it for questions such as:

- Is a company registered with the California Secretary of State?
- What is the entity number, status, standing, entity type, initial filing date, or formation jurisdiction?
- What registered agent or address did the public registry return?
- Which companies in a short list look active, suspended, forfeited, dissolved, or otherwise need review?

Do not use it for California tax balances, certified copies, private account data, LLP or general-partnership records that the portal does not index, or legal conclusions. The status risk score is a transparent triage signal, not a legal, credit, or compliance opinion.

### Input

```json
{
  "businessNames": ["Apple Inc", "C0806592"],
  "maxItems": 10,
  "includeRawFields": false,
  "requestDelayMs": 2500
}
```

`businessNames` is required and accepts company names or entity numbers. `maxItems` defaults to 10 and caps the total unique records across all queries. `includeRawFields` defaults to false and can be enabled when you need the original fields returned by the registry. `requestDelayMs` defaults to 2500 milliseconds between separate searches.

### Output

One dataset item is emitted per unique registry row. The stable fields are:

| Field | Description |
| --- | --- |
| `entityName` | Registered entity name |
| `entityNumber` | California entity/file number when returned |
| `status` | Public registry status |
| `standing` | Public standing value when returned |
| `entityType` | Entity classification |
| `formationDate` | Initial filing or formation date |
| `jurisdiction` | Formed-in state or country |
| `registeredAgent` | Public agent text |
| `principalAddress` | Principal address when returned |
| `mailingAddress` | Mailing address when returned |
| `riskScore` | 0-100 triage score from status and standing text |
| `riskLevel` | `low`, `medium`, `high`, or `critical` |
| `riskSignals` | Human-readable reasons for the score |
| `searchQuery` | Input query that produced the row |
| `sourceUrl` | Official BizFile Online search page |
| `scrapedAt` | ISO 8601 collection timestamp |
| `rawFields` | Original row fields when opted in; otherwise `null` |

Active or good-standing text maps to a low score. Suspended, inactive, delinquent, or not-good-standing text maps to a high score. Dissolved, cancelled, revoked, surrendered, merged, or forfeited text maps to a critical score. Unknown or missing status text is intentionally called out rather than silently treated as healthy.

The `OUTPUT` key-value record contains terminal status, counts, warnings, and target diagnostics. An empty match is a successful empty run. If Imperva blocks every search, the run is marked blocked with a diagnostic message rather than pretending that the business names have no matches.

### Pricing

Pricing is configured as pay-per-event:

- `apify-actor-start`: $0.00005 once per run.
- `sos-record`: $0.008 per unique normalized record returned.

The actor also supports Apify's compute and proxy usage billing when enabled in Console. The `maxItems` cap gives agents and batch workflows a predictable upper bound on result charges.

### JavaScript API

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('YOUR_USERNAME/sos-scraper').call({
  businessNames: ['Apple Inc', 'C0806592'],
  maxItems: 10
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Python API

```python
from apify_client import ApifyClient
import os

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("YOUR_USERNAME/sos-scraper").call({
    "businessNames": ["Apple Inc", "C0806592"],
    "maxItems": 10,
})
items = list(client.dataset(run["defaultDatasetId"]).iterate_items())
print(items)
```

### Reliability notes

BizFile Online is a JavaScript single-page application protected by Imperva. The actor keeps the seed navigation and API request in the same Playwright session and uses the official request payload observed by the application. When configured, it tries the DataImpulse gateway first with a consistent browser session and automatically moves to the configured Apify proxy tier if the DataImpulse tunnel fails. If both proxy paths are blocked, the run reports a target-access diagnostic. The actor does not attempt to evade a CAPTCHA, reuse user cookies, or submit private information.

Public government data can change. Field mapping is defensive and preserves optional raw fields when requested. The actor caps concurrency at one browser request and includes a configurable delay to avoid unnecessary load. Use scheduled runs for monitoring rather than a tight polling loop.

### Legal and data-use notice

This actor accesses publicly displayed business-registry information. Users are responsible for complying with the California Secretary of State website terms, applicable laws, privacy obligations, and any downstream data-use restrictions. The data is not certified, and the California Secretary of State is the authoritative source for legal reliance.

### FAQ

#### Why did a run return no records?

The query may have no matching indexed entity, or the target may have returned a valid empty response. Check the `OUTPUT` warnings and try the registered name or entity number.

#### Why did a run become blocked?

Imperva can reject a browser session before the JSON search executes. The actor uses DataImpulse first when its secret environment variables are configured, then the default Apify proxy tier when the DataImpulse tunnel is unavailable. Persistent blocks mean the advertised public mode is unavailable for that run; the actor reports this explicitly.

#### Does this download filing PDFs?

No. It is a read-only structured business-search actor. It does not order documents or access authenticated filing workflows.

#### Can I search all California businesses?

Use a bounded list of names or entity numbers. This actor is designed for targeted lookups and bounded batches; `maxItems` is capped at 10,000 to keep runtime, load, and billing predictable.

#### What does the risk score mean?

It is a deterministic mapping of returned status and standing text. It flags records for review; it does not determine legal good standing, solvency, tax compliance, or fraud.

# Actor input Schema

## `businessNames` (type: `array`):

Use this when looking up one or more California business names or entity numbers. Enter one search value per line, for example 'Apple Inc' or 'C0806592'. The default is a public sample company. Do not enter passwords, tax identifiers, or private personal data.

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

Use this to cap the total number of unique registry records returned across all searches. Enter a number from 1 to 10000. The default is 10 and the cap prevents accidental large runs against a public registry. This is not the maximum number of matches the state stores.

## `includeRawFields` (type: `boolean`):

Use this when you need unmapped fields from the state's search row for downstream debugging or schema discovery. The default is false to keep agent output compact. Raw fields are public response data, not a certified filing image or a guarantee of completeness.

## `requestDelayMs` (type: `integer`):

Use this to pace separate registry searches within the browser session. Enter a number from 1000 to 30000 milliseconds; the default is 2500. A delay reduces load but does not defeat an Imperva block or guarantee a response.

## Actor input object example

```json
{
  "businessNames": [
    "Apple Inc"
  ],
  "maxItems": 25,
  "includeRawFields": false,
  "requestDelayMs": 2500
}
```

# Actor output Schema

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

Normalized business entity records returned by the official registry.

## `datasetCsv` (type: `string`):

The normalized registry records as CSV.

## `summary` (type: `string`):

Terminal status, counts, warnings, and target diagnostics.

## `consoleRun` (type: `string`):

Live run status, logs, and dataset preview.

# 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 = {
    "businessNames": [
        "Apple Inc"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("muhammadafzal/sos-scraper").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 = { "businessNames": ["Apple Inc"] }

# Run the Actor and wait for it to finish
run = client.actor("muhammadafzal/sos-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "businessNames": [
    "Apple Inc"
  ]
}' |
apify call muhammadafzal/sos-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=muhammadafzal/sos-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/FWyifkFy8BYnWp7rg/builds/DhFWtVfPktUMA7FM6/openapi.json
