# California State Bar Attorney Scraper (`normdata/calbar-scraper`) Actor

Scrape California State Bar attorney profiles: name, license status, firm, address, phone, website, law school, admission date, practice areas, specialties, languages and full discipline history. Search by county, city, practice area, language or license number.

- **URL**: https://apify.com/normdata/calbar-scraper.md
- **Developed by:** [Norm Data](https://apify.com/normdata) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $15.00 / 1,000 attorneys

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

![Norm Data](https://raw.githubusercontent.com/FabriAV/normdata/refs/heads/main/assets/banner_norm2.png)

## ⚖️ California State Bar Attorney Scraper

Extract attorney records from the **State Bar of California** licensee search, the official register of every lawyer licensed in California. Search by **county, city, state, ZIP, practice area, certified specialty, language, name or firm**, or scan **license numbers** to cover every status. Each attorney comes with the **license status, firm, full address, phone, fax, website, law school, admission date, practice areas, certified specialties, languages and the complete license and discipline history** with case numbers.

Each attorney comes with:

- **Contact:** firm, street, city, state, ZIP, phone, fax and website.
- **License:** license number, status (active, inactive, disbarred, resigned, not eligible), status date, admission date and years licensed.
- **Practice:** self-reported practice areas, State Bar certified specialties, California Lawyers Association sections and languages spoken by the attorney and by their staff.
- **Background:** law school and any other name the attorney has used.
- **Discipline:** consumer alerts, number of discipline cases, and every history entry with date, status, discipline, case number and administrative action.

### 🎯 Who uses it?

#### 📞 Legal marketing and lead generation agencies

Build lists of active family, immigration or personal injury attorneys in any California county, with phones, addresses and websites ready for outreach.

#### 🧑‍💼 Legal recruiters and law firms

Find attorneys by practice area, certified specialty, language, law school and year of admission.

#### 🛡️ Compliance, insurance and background checks

Verify that a lawyer is licensed and in good standing, and pull the full discipline history with State Bar Court case numbers.

#### 📊 Researchers and journalists

Study the California legal market: where attorneys practice, which schools they come from, how discipline is spread across the bar.

### ✨ What it does

- **Search like the State Bar's advanced search:** counties (all 58 plus non-California), cities, US states, ZIP codes, 66 practice areas, 22 certified specialties, 99 languages, last, first and middle name (begins with, exact, contains or sounds like) and firm name. Lists match ANY of their values.
- **No 500 result cap:** the State Bar site shows at most 500 results per search. The scraper splits big searches by name automatically, so you get every match, even every active attorney in Los Angeles.
- **Every status with the license number range:** the State Bar search only lists active attorneys. Scan a range of license numbers to get inactive, disbarred, resigned and not eligible attorneys too.
- **Result filters:** license status, admission year range, law school, discipline record (with or without), phone only, website only, certified specialists only.
- **Or paste profile links or license numbers.** With links, the filters are ignored.
- **One row per attorney,** even when several searches find the same person.

### 🏆 Why this scraper

- **The official source.** Data comes straight from the State Bar of California, the body that licenses and disciplines attorneys.
- **Full profiles in every row.** Each attorney's profile page is read, so phone, fax, website, law school, specialties, languages and history are always included at no extra cost.
- **Complete discipline history.** Every entry with date, status, discipline, State Bar Court case number and administrative action, as a clean list, plus a `disciplineCases` count and a `hasDiscipline` yes/no field.
- **Clean data.** Address split into firm, street, city, state and ZIP; dates as YYYY-MM-DD; first, middle and last name separated; websites as full links.
- **Fast and polite.** Around 1,100 to 1,300 attorneys a minute, at a pace the State Bar site handles easily, slowing down by itself if the site asks.
- **No proxy needed.**

### 📦 What data you get

| Field | Description |
| --- | --- |
| `name`, `firstName`, `middleName`, `lastName` | Full name and its parts. |
| `alsoKnownAs` | Another name the attorney has used (when listed). |
| `licenseNumber` | State Bar license number. |
| `status` | `Active`, `Inactive`, `Not Eligible to Practice Law`, `Disbarred`, `Resigned` and a few rarer ones. |
| `consumerAlert` | The State Bar's consumer alert text (for example for disbarred attorneys). |
| `firm`, `street`, `city`, `state`, `zipCode` | Address of record, split. |
| `address` | Address of record as shown. |
| `phone`, `fax` | Phone and fax. |
| `lawSchool` | Law school and its location. |
| `yearsLicensed` | Full years since admission to the California bar. |
| `disciplineCases` | Number of discipline cases in the history. |
| `certifiedSpecialist`, `hasDiscipline`, `claMember` | Certified legal specialist, has a discipline record, California Lawyers Association member. |
| `url`, `website` | State Bar profile and the attorney's website. |
| `certifiedSpecialties` | State Bar certified specialties, e.g. `Family Law (State Bar of California)`. |
| `practiceAreas` | Self-reported practice areas. |
| `claSections` | California Lawyers Association sections. |
| `languages`, `staffLanguages` | Languages spoken by the attorney and by their staff. |
| `history` | Every license and discipline entry: `date`, `licenseStatus`, `discipline`, `caseNumber`, `administrativeAction`. |
| `admissionDate`, `statusSince` | Admitted to the California bar, and since when the current status applies. |
| `scrapedAt` | When the row was saved. |
| `error` | Only when a profile could not be read. |

#### Example row (trimmed)

```json
{
  "name": "Laura Elizabeth Alterman",
  "firstName": "Laura",
  "middleName": "Elizabeth",
  "lastName": "Alterman",
  "alsoKnownAs": "Laura Elizabeth Vocke",
  "licenseNumber": 274556,
  "status": "Active",
  "firm": "DeLacey, Riebel & Shindell, LLP",
  "street": "180 Montgomery St, Ste 1900",
  "city": "San Francisco",
  "state": "CA",
  "zipCode": "94104-4278",
  "phone": "415-528-7000",
  "fax": "415-528-7001",
  "lawSchool": "U of San Francisco SOL; San Francisco CA",
  "yearsLicensed": 15,
  "disciplineCases": 0,
  "certifiedSpecialist": true,
  "hasDiscipline": false,
  "claMember": true,
  "url": "https://apps.calbar.ca.gov/attorney/Licensee/Detail/274556",
  "website": "https://www.drsfamilylaw.com/our-attorneys/laura-e-alterman",
  "certifiedSpecialties": ["Family Law (State Bar of California)"],
  "practiceAreas": ["Family Law"],
  "claSections": ["Family Law"],
  "history": [{ "date": "2010-12-09", "licenseStatus": null, "discipline": null, "caseNumber": null, "administrativeAction": "Admitted to the State Bar of California" }],
  "admissionDate": "2010-12-09"
}
```

### 💡 Use cases

#### 👪 Every certified family law specialist in San Francisco

```json
{ "counties": ["SF"], "specialties": ["04"], "maxItems": null }
```

#### 🗣️ Spanish speaking immigration attorneys in Los Angeles County with a phone

```json
{ "counties": ["LA"], "practiceAreas": ["34"], "languagesSpoken": ["1"], "withPhoneOnly": true, "maxItems": null }
```

#### 🎓 Attorneys admitted 2015 to 2020 in Fresno

```json
{ "cities": ["Fresno"], "admittedFrom": 2015, "admittedTo": 2020, "maxItems": null }
```

#### 🚨 Disbarred attorneys among license numbers 100,000 to 150,000

```json
{ "licenseNumberFrom": 100000, "licenseNumberTo": 150000, "statuses": ["disbarred"], "maxItems": null }
```

#### 🆕 Newly licensed attorneys (every license since 365,000)

```json
{ "licenseNumberFrom": 365000, "maxItems": null }
```

#### 🔎 Check specific attorneys

```json
{ "licenses": ["252110", "https://apps.calbar.ca.gov/attorney/Licensee/Detail/102694"] }
```

### ⚙️ How the input is organised

| Section | What it's for |
| --- | --- |
| **Maximum results** | Always first: caps the whole run (empty means no limit). |
| **Search filters** | Counties, cities, states, ZIP codes, practice areas, specialties, languages, names and firm. Active attorneys only. |
| **Result filters** | Status, admission years, law school, discipline, phone, website, certified specialists. |
| **Or scan license numbers** | Every attorney in a license number range, any status. The search filters are not used; the result filters are. |
| **Or scrape links** | Profile links or license numbers. With links, the filters are ignored. |
| **Proxy** | Optional. |

**Links and filters are not mixed:** with links, the search fields and filters are ignored and the log says so.

### 💰 Pricing

Pay-per-event: a one-time **0.003** when the run starts, plus a price per attorney saved:

| Charged for | Free | Bronze | Silver | Gold+ |
| --- | --- | --- | --- | --- |
| **Attorney**: one full State Bar profile with status, contact details, practice areas, specialties, languages and discipline history | 0.021 | 0.019 | 0.017 | 0.015 |

New Apify accounts start with $5 in free credit. The Apify Free plan is limited to 10 results per run.

### 🚀 Run it

1. Create a free Apify account with $5 in credit.
2. Open the California State Bar Attorney Scraper.
3. Fill in the input (or keep the prefilled example), set the maximum number of results, then click **Start**.
4. Export the results as CSV, Excel, JSON, or XML from the Dataset tab.

Run it programmatically through the Apify API (`run-sync-get-dataset-items`) or the ApifyClient for JavaScript and Python, and schedule it with Apify's built-in Scheduler.

### 🤖 Use with AI agents (MCP)

Give an AI agent live California attorney data through the Model Context Protocol:

```
claude mcp add --transport http apify "https://mcp.apify.com?tools=normdata/calbar-scraper"
```

Then prompt it in plain language, for example "list the certified family law specialists in Orange County with their phones and websites".

### 🔧 Troubleshooting

**I only get active attorneys.**
The State Bar search lists active attorneys only. Use the license number range (with the status filter if you like) to get inactive, disbarred, resigned and not eligible attorneys.

**My status filter stopped the run.**
A status other than active needs the license number range, for the reason above. The log explains it.

**Some license numbers are missing from a range.**
The State Bar shows no public profile for deceased attorneys and some others, and not every number was issued. Those numbers are skipped.

**The county filter did nothing in a range scan.**
Profiles do not show the county, so the search filters are not used with a license number range. The log says which were skipped. The result filters still apply.

**Some attorneys found by name show a different name.**
The State Bar name search also matches former names (for example a maiden name). The row shows the attorney's current name, as on the profile.

**Runs over a whole county take a while.**
Every attorney's profile is read (that is where phones, history and specialties are). Expect around 1,100 to 1,300 attorneys a minute (1,000 in under a minute); for runs of tens of thousands raise the run timeout.

### ❓ FAQ

| Question | Answer |
| --- | --- |
| Do I need a State Bar account? | No. Only the public attorney search is read. |
| Are emails included? | No. The State Bar protects attorney emails against automated collection, so they are not extracted. Rows have the phone, fax, address and website. |
| How fresh is the data? | Live: every run reads the current State Bar records. |
| Is the practice area data official? | Practice areas and languages are self-reported by attorneys. Certified specialties, status, admission and discipline are State Bar records. |
| Does it need a proxy? | No. There is an optional proxy setting if the site ever slows down your runs. |

### 🛡️ Limits & responsible use

This Actor reads only public pages of the State Bar of California attorney search. It never signs in, keeps a polite pace, respects robots.txt and does not collect the email addresses the State Bar protects. Use the data in line with the State Bar's terms and the laws on contacting people (for example the TCPA and CAN-SPAM in the US, and the CCPA in California). Discipline records are public, but always check the State Bar profile before relying on them.

### 📧 Contact

Need a scraper for a different site, or found something wrong with this one? norm.data.scrapers@gmail.com

### 🧪 Local development

```powershell
bun install
bun run typecheck
bun test/qa.mjs
apify run
```

Local results are stored in `storage/datasets/default`.

# Actor input Schema

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

Stop after this many attorneys. Leave empty for no limit. The Apify Free plan is always capped at 10.

## `counties` (type: `array`):

Attorneys whose address is in ANY of these California counties ("Non-California" = addresses outside the state).

## `cities` (type: `array`):

Attorneys in ANY of these cities, e.g. "San Diego". One per line.

## `cityMatch` (type: `string`):

How the city is matched. Begins with when not set.

## `states` (type: `array`):

Attorneys whose address is in ANY of these US states (many California attorneys live elsewhere).

## `zipCodes` (type: `array`):

Attorneys in ANY of these 5 digit ZIP codes. One per line.

## `practiceAreas` (type: `array`):

Attorneys who report ANY of these practice areas (self-reported to the State Bar).

## `specialties` (type: `array`):

Attorneys certified as specialists in ANY of these areas.

## `languagesSpoken` (type: `array`):

Attorneys listed as speaking ANY of these languages.

## `lastName` (type: `string`):

e.g. "Garcia".

## `lastNameMatch` (type: `string`):

Begins with when not set.

## `firstName` (type: `string`):

e.g. "Maria".

## `firstNameMatch` (type: `string`):

Begins with when not set.

## `middleName` (type: `string`):

Middle name or initial.

## `middleNameMatch` (type: `string`):

Begins with when not set.

## `firmName` (type: `string`):

e.g. "Latham".

## `firmNameMatch` (type: `string`):

Contains when not set.

## `statuses` (type: `array`):

Keep only ANY of these statuses. The search filters find active attorneys only; the other statuses need the license number range.

## `admittedFrom` (type: `integer`):

Keep only attorneys admitted to the California bar in this year or later.

## `admittedTo` (type: `integer`):

Keep only attorneys admitted in this year or earlier.

## `lawSchool` (type: `string`):

Keep only attorneys from a law school whose name contains these words, e.g. "Hastings" or "UCLA".

## `discipline` (type: `string`):

Any when not set. "With" keeps attorneys with any public discipline or charges in their history; "Without" keeps a clean record.

## `withPhoneOnly` (type: `boolean`):

Keep only attorneys with a phone number.

## `withWebsiteOnly` (type: `boolean`):

Keep only attorneys with a website.

## `certifiedSpecialistsOnly` (type: `boolean`):

Keep only attorneys certified as legal specialists.

## `licenseNumberFrom` (type: `integer`):

First license number. 1 when only "to" is set.

## `licenseNumberTo` (type: `integer`):

Last license number. Leave empty to read up to the newest license.

## `licenses` (type: `array`):

apps.calbar.ca.gov/attorney/Licensee/Detail/123456 links, or license numbers like 123456. One per line.

## `proxyConfiguration` (type: `object`):

Optional, off by default. The State Bar site works without one. Proxy traffic is billed to your Apify account.

## Actor input object example

```json
{
  "maxItems": 10,
  "counties": [
    "SF"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (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 = {
    "maxItems": 10,
    "counties": [
        "SF"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("normdata/calbar-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 = {
    "maxItems": 10,
    "counties": ["SF"],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("normdata/calbar-scraper").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 '{
  "maxItems": 10,
  "counties": [
    "SF"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call normdata/calbar-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,normdata/calbar-scraper"
        }
    }
}
```

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/Dc4juQ7p1zlf2l0Di/builds/4g32LxWBCOhH4pclN/openapi.json
