# New York State Bar Attorney Scraper — License Lookup & Leads (`scrapersdelight/state-bar-attorney-scraper`) Actor

Every attorney on the New York bar register: name, bar number, status, firm, firm head-count, phone, business address, county, law school and admission year. Filter to solo and small firms, a county or an admission-year cohort — or look up a registration number to verify a licence. No API key.

- **URL**: https://apify.com/scrapersdelight/state-bar-attorney-scraper.md
- **Developed by:** [Scrapers Delight](https://apify.com/scrapersdelight) (community)
- **Categories:** Lead generation, Business, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.00 / 1,000 per attorney returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## New York State Bar Attorney Scraper — License Lookup & Leads

**Every attorney on the New York bar register, from the state's own open-data feed at
[data.ny.gov](https://data.ny.gov/Transparency/NYS-Attorney-Registrations/eqw2-r5nb).** One row per
attorney registration: **registration (bar) number, full name split into first/middle/last, firm,
firm head-count, phone, business address, city, state, ZIP, county, law school, year admitted, years
licensed, judicial department, registration status and next registration due.** Filter by status,
county, city, address state, admission-year cohort or firm size — or paste registration numbers and
surnames to verify specific attorneys. **No login, no API key, no CAPTCHA, no proxy needed.**

**432,690 registrations. 293,648 currently registered. 251,320 of those carry a phone or a street
address** — every count measured live on 2026-08-12, not quoted from a marketing page. Phone fill on
that default slice is **100%**.

#### 🚀 Quick start

The Actor ships prefilled with a working demo — **statuses: Currently registered · county: New York
(Manhattan) · 100 rows**. Press **Start** with zero edits and you get 100 currently-registered
Manhattan attorneys with firm, firm head-count, phone, street address, ZIP, county, law school and
admission year. There are 77,761 attorneys behind that filter; you get the first 100 of them — raise `maxItems`
when you want the rest.

```json
{
  "statuses": ["Currently registered"],
  "counties": ["New York"],
  "maxItems": 100
}
```

Three more inputs worth copying:

```jsonc
// 1. The legal-SaaS ICP: solo and small-firm attorneys, statewide, reachable
{ "statuses": ["Currently registered"], "withContactOnly": true, "maxFirmSize": 5, "maxItems": 5000 }

// 2. Licence verification — searches EVERY status, including disbarred and deceased
{ "registrationNumbers": ["1000629", "2222222"] }

// 3. This year's admits — the bar-prep / first-practice-management-tool cohort (4,988 of them)
{ "statuses": ["Currently registered"], "admittedFromYear": 2026, "maxItems": 5000 }
```

#### ✨ Why use this scraper

- **Firm head-count on every row.** `firmAttorneyCount` is computed across the whole
  currently-registered register before a single row is emitted, so `maxFirmSize: 5` hands you solo
  and small-firm attorneys and leaves BigLaw behind. No other attorney or law-firm scraper on this
  Store advertises a firm head-count field. Details and the measured normalisation are two sections
  down.
- **It is the register, not a marketing directory.** Status, registration number and admission year
  come from the New York State Unified Court System's own file, published under 22 NYCRR 118.
- **Fast, because it is bulk data, not a search form.** Other state-bar scrapers drive a name-search
  page one query at a time and warn that a full-state crawl takes hours. This one asks New York's
  Socrata API for the slice you want. **The prefilled default run returned 100 rows in 9.4-10.9 seconds
  on Apify**, measured over three consecutive runs on 2026-08-14. A 1,000-row Manhattan pull
  measured 10.7 seconds on the same path, so the cost is the row cap, not the wait.
- **The dead people are already filtered out.** 49,199 of the 432,690 registrations are deceased
  attorneys — 11.4% of the file. The `statuses` prefill removes them before you are billed for one.
- **Verification and lead-gen in one Actor.** A registration-number lookup deliberately overrides the
  status prefill so a disbarred or suspended attorney still comes back. A licence check that hides a
  bad status is worse than no check.
- **No wall to beat, and we say so.** `data.ny.gov` is a public open-data API: no key, no login, no
  anti-bot, no geo gate. Measured 16/16 requests OK direct from an Apify container over 16,000 rows,
  0 duplicates. The proxy field defaults to off because a proxy here only adds a failure mode.
- **Pagination that cannot silently skip rows.** Every request pins `$order=registration_number`,
  and the run asserts uniqueness as it walks.

#### 🎯 Use cases

| You are a… | Use it to… |
|---|---|
| **Practice-management / legal-tech SaaS** (Clio, MyCase, Filevine, Smokeball, Lawmatics class) | Pull `maxFirmSize: 5` — solo and small-firm attorneys are the entire ICP, pre-filtered, with a phone number on 100% of the default slice |
| **Malpractice-insurance broker or carrier** | Segment by `yearsLicensed`, county and firm size; renewal timing keys off `nextRegistrationDue` |
| **CLE and bar-prep marketer** | Set `admittedFromYear` to the current year — 4,988 attorneys were admitted in 2026 so far |
| **Compliance / vendor onboarding** | Paste `registrationNumbers` and get status, admission year and judicial department back for each; disbarred and suspended attorneys are returned, not hidden |
| **Legal recruiter** | Filter a county, then cut by `lawSchool` and `yearAdmitted` after export |
| **Law-firm M\&A and succession advisor** | `maxFirmSize: 1` plus `admittedToYear: 1990` is a list of long-tenured solos with no succession plan |
| **Legal directory / lead marketplace** | Seed a New York directory from the authoritative register instead of scraping five commercial ones |

#### 📥 Supported inputs

| Input | Example | What it does |
|---|---|---|
| `statuses` | `["Currently registered"]` | Multi-select of the 11 exact New York status strings, each labelled with its live row count |
| `withContactOnly` | `true` | Keep only rows with a phone or street address (251,320 of 293,648) |
| `registrationNumbers` | `["1000629"]` | Licence verification by bar number; searches all statuses |
| `lastNames` | `["BRODY"]` | Exact surname match, case-insensitive (BRODY = 93 registrations) |
| `counties` | `["New York"]` | Multi-select of all 62 NY counties with counts |
| `cities` | `["BROOKLYN"]` | Free text, case-insensitive |
| `states` | `["NJ"]` | Business-address state, multi-select |
| `admittedFromYear` / `admittedToYear` | `2026` | Admission-year cohort |
| `maxFirmSize` | `5` | Solo / small-firm filter on the computed head-count |
| `maxItems` | `100` | Hard row cap, and your cost ceiling. Raise it for a real pull |

**Not supported:** email addresses (New York publishes none — see Honest limits), states other than
New York, disciplinary case documents, fuzzy or prefix name search (`lastNames` is an exact match),
and anything behind a login. This Actor reads one public file and does not touch the courts' own
attorney-search web app.

### The small-firm filter — the reason to use this over a CSV download

Clio, MyCase, Filevine, Smokeball and Lawmatics do not sell to Kirkland & Ellis, which alone has
**1,242** registered New York attorneys. Before it walks a single row this Actor sweeps the whole
register grouped by firm and stamps a **`firmAttorneyCount`** on every record. Then:

- `maxFirmSize: 1` → **solo practitioners**
- `maxFirmSize: 5` → **solo and small firms** — 115,242 currently-registered attorneys sit at firms
  of five or fewer (measured 2026-08-12)
- `maxFirmSize: 20` → boutiques and below
- empty → everyone, BigLaw included

Attorneys who list no firm at all (typically solos and in-house counsel) are always kept. The
head-count is measured across **currently-registered NY attorneys statewide**, not just within your
result slice, so it means the same thing on every row.

#### Why the head-count is normalised, and why that matters to you

Attorneys type their own firm name, so the raw strings fragment badly:

| Raw `company_name` | Attorneys |
|---|---:|
| KIRKLAND & ELLIS LLP | 977 |
| KIRKLAND & ELLIS | 174 |
| KIRKLAND AND ELLIS LLP | 43 |
| KIRKLAND & ELLIS, LLP | 26 |
| KIRKLAND AND ELLIS | 12 |

One firm, five spellings. A naive `GROUP BY company_name` would tell you a Kirkland partner works
somewhere with **12** lawyers and drop them into your small-firm list. Measured on 2026-08-12 across
the currently-registered register — the same population the head-count is computed over — grouping
raw puts **128,524** attorneys at firms of five or fewer; grouping normalised puts **115,242** there.
The naive version mislabels **13,282 BigLaw attorneys (10.3%) as small-firm leads.**

So this Actor case-folds, expands `&`, strips punctuation and strips entity suffixes
(`LLP`/`LLC`/`PLLC`/`PC`/`LP`/`PA`/…) before counting — **109,325 raw name strings collapse to 96,549
firms.** Placeholders like `SELF EMPLOYED`, `SOLE PRACTITIONER`, `RETIRED` and `N/A` (816 attorneys)
are treated as *no firm* rather than pooled into one giant pseudo-firm, so those solos stay in your
small-firm list where they belong.

The five largest firms in the register after normalisation, if you want to sanity-check it yourself:
Kirkland & Ellis 1,242 · Latham & Watkins 1,208 · Simpson Thacher & Bartlett 1,118 · Paul Weiss 983 ·
Davis Polk & Wardwell 947.

Honest residual: normalisation is string-based, not entity resolution. It will not merge
`SKADDEN ARPS` with `SKADDEN, ARPS, SLATE, MEAGHER & FLOM`, and a firm whose three attorneys each
invented a different abbreviation will still read as three ones. The error that remains is a small
under-count at the low end, never the 900-attorney over-inclusion the raw version produces.

### 📦 Output sample

One real row, exactly as the Actor emitted it on 2026-08-12:

```jsonc
{
  "registrationNumber": "1000322",
  "fullName": "RONALD GABRIEL RUSSO",
  "firstName": "RONALD",
  "middleName": "GABRIEL",
  "lastName": "RUSSO",
  "suffix": null,

  "firmName": "SCHLAM STONE & DOLAN, LLP",
  "firmAttorneyCount": 22,

  "phone": "(917) 207-9328",
  "address": "26 BROADWAY STE 1900",
  "address2": null,
  "city": "NEW YORK",
  "state": "NY",
  "zip": "10004-1703",
  "county": "New York",
  "country": "UNITED STATES OF AMERICA",

  "yearAdmitted": 1974,
  "yearsLicensed": 52,
  "judicialDepartment": 2,
  "lawSchool": "St. John's University School of Law",

  "status": "Currently registered",
  "isCurrentlyRegistered": true,
  "nextRegistrationDue": "2028-03",
  "hasContact": true,

  "sourceUrl": "https://iapps.courts.state.ny.us/attorneyservices/search",
  "scrapedAt": "2026-08-13T01:42:51.424Z"
}
```

Four fields people misread:

- **`firmAttorneyCount: null` is not zero.** It means the attorney listed no firm, or listed a
  placeholder like `RETIRED`. Those rows are always kept by `maxFirmSize`, because an attorney with
  no firm is the smallest firm there is. A literal **`0`** is different again: the firm is named, but
  it has no currently-registered New York attorney left — which is what you see on deceased,
  resigned and disbarred rows returned by a licence lookup or an all-statuses run.
- **`firmAttorneyCount` counts currently-registered New York attorneys only.** A national firm's real
  head-count is larger; this is its New York bar footprint, which is the number that matters when you
  are deciding whether it is a small-firm lead.
- **`nextRegistrationDue` is `YYYY-MM`, not a date.** New York publishes a month and a year
  ("May 2028"); nothing more precise exists.
- **Names and firms are returned exactly as New York publishes them — mostly upper case.** They are
  not title-cased, because doing so corrupts `McDONALD` and `O'BRIEN`. Case-fold at your end.

### 🗂 Key output fields

| Field | Type | Notes |
|---|---|---|
| `registrationNumber` | string | New York bar number. The dedupe key — unique per attorney |
| `fullName`, `firstName`, `middleName`, `lastName`, `suffix` | string | As published; `suffix` is filled on 1.8% of rows |
| `firmName` | string | Raw string as typed by the attorney |
| `firmAttorneyCount` | integer | **Computed by this Actor**, not published by New York |
| `phone` | string | Normalised to `(XXX) XXX-XXXX` |
| `address`, `address2`, `city`, `state`, `zip`, `country` | string | Registered business address; ZIP includes +4 when published |
| `county` | string | **In-state addresses only** — 53.9% of the default slice |
| `yearAdmitted`, `yearsLicensed` | integer | `yearsLicensed` is computed from the current year |
| `judicialDepartment` | integer | Appellate Division department of admission, 1–4 |
| `lawSchool` | string | 99.9% filled on the default slice |
| `status`, `isCurrentlyRegistered` | string / boolean | One of the 11 exact New York status strings |
| `nextRegistrationDue` | string | `YYYY-MM` — New York's biennial re-registration month |
| `hasContact` | boolean | True when a phone or street address is present |
| `sourceUrl`, `scrapedAt` | string | Provenance. `scrapedAt` is ISO-8601 UTC |

There is no `email` field, and none can be produced from this source.

### Field fill — measured on the 251,320-row default slice

Exact counts over every currently-registered attorney with contact details, measured 2026-08-12 —
not a sample, not an estimate:

| Field | Fill |
|---|---:|
| name, registration number, admission year, judicial dept., status | **100%** |
| **`phone`** | **100%** |
| `nextRegistrationDue` | 100% |
| `lawSchool` | 99.9% |
| `address` / `city` | 93.1% |
| **`firmName`** | **87.9%** |
| `firmAttorneyCount` | 87.9% minus the 816 rows carrying a placeholder |
| `state` / `zip` | 84.5% |
| `middleName` | 79.6% |
| **`county`** | **53.9%** |
| `address2` | 8.1% |
| `suffix` | 1.8% |

**The number that could mislead you: `county` is 53.9%, because New York only populates it for
in-state addresses** — 135,579 of the 251,320 rows in the default slice. On a wider basis it is
thinner still: the same 135,579 rows are only 46.2% of all 293,648 currently-registered attorneys,
and 163,314 rows carry a county across the whole 432,690-row file. Filtering by county therefore
silently restricts you to New York-based attorneys — usually
what you want, but choose it deliberately. `state`/`zip` trail `city` by ~9 points for the same
reason: a slice of registrants give a foreign or incomplete address, and `country` is returned so you
can drop them.

`address2` (8.1%) and `suffix` (1.8%) are thin because New York genuinely publishes them that
rarely, not because they are missed: the registry’s own column statistics report `street_2` on
23,439 of 432,758 registrations and `suffix` on 7,871 — re-measured against the live source on
2026-08-19, and the Actor returns every one of them.

**The defaults are worth roughly 3.5× on every contact field.** With `statuses` and `withContactOnly`
cleared, a live run over the raw file returned the first 1,500 rows at **28.2% phone, 24.3% address,
21.5% firm** (reproduced 2026-08-12). Every run prints its own measured fill in the log.

### Read this before you run it

1. **432,690 registrations is not 432,690 leads.** 49,199 of them — 11.4% of the file — are deceased
   attorneys, and another 49,428 are delinquent, suspended, resigned, disbarred or incapacitated.

   | Status | Rows |
   |---|---:|
   | **Currently registered** | **293,648** |
   | Deceased | 49,199 |
   | Due to reregister within 30 days of birthday | 40,415 |
   | Suspended, delinquent | 19,097 |
   | Delinquent | 16,492 |
   | Resigned | 7,136 |
   | Disbarred | 2,190 |
   | Incapacitated | 1,904 |
   | Suspended, currently registered | 1,405 |
   | Resigned from bar - disciplinary reason | 718 |
   | Suspended, due to reregister | 486 |

2. **A registration-number lookup ignores your status and contact filters, on purpose.** Verifying a
   licence under the `Currently registered` prefill would hide exactly the attorneys you are checking
   for. The run logs that it switched modes.

3. **`county` restricts you to New York-based attorneys.** See the fill table above.

4. **One row per registration, and a registration number belongs to one attorney.** The Actor
   deduplicates on it while it walks and warns if it ever sees a repeat.

5. **A registration number that does not exist fails the run rather than returning an empty
   dataset** — with a message naming the number. That is the verification answer, and it costs you
   nothing because no row was delivered.

### 💰 Pricing

**$0.003 per attorney returned — $3.00 per 1,000.** Charged on the `attorney-scraped` event. No
monthly platform fee from this Actor.

| Run | Attorneys | Cost |
|---|---:|---:|
| Default prefilled run (Manhattan, currently registered) | 100 | $0.30 |
| 1,000 Manhattan attorneys (`maxItems: 1000`) | 1,000 | $3.00 |
| Everyone admitted in 2026 | 4,988 | $14.96 |
| Every currently-registered attorney in Manhattan | 77,761 | $233.28 |
| Every currently-registered attorney with contact details, statewide | 251,320 | $753.96 |
| The entire register, every status including the deceased | 432,690 | $1,298.07 |

Rows are charged as they are pushed — hit a budget cap and you get whole rows and stop, never a
half-billed dataset. Verified on the run behind this page: 1,000 rows delivered, exactly 1,000
`attorney-scraped` events charged. **You are never charged for a row your filters removed:** `statuses`,
`counties`, `cities`, `states` and the admission-year cohort are applied server-side by New York, so
those rows are never even fetched, and `maxFirmSize` drops rows before they reach the dataset. You
are never charged twice for the same registration number. **`maxItems` is your hard cost cap**
(default 100; there is no unbounded mode — set it to the number you want).

### Honest limits

- **No email addresses. New York publishes none, for any attorney.** Name, firm, postal address,
  phone, county, law school, admission year and status are what 22 NYCRR 118 requires and all that
  exists in this file. There is no `email` field and nothing here can produce one. Phone (100% of the
  default slice) and postal mail (93.1%) are the channels. Anyone selling you "New York bar emails"
  generated them somewhere else.
- **New York only.** Not a national dataset, and this page does not imply it is. See the FAQ for why
  Florida was evaluated and rejected.
- **`county` is 53.9%** of the default slice, and only exists for in-state addresses.
- **`state`/`zip` are 84.5%, `firmName` 87.9%.** A missing firm means the attorney did not file one,
  not a scraping failure — the field is self-reported on the biennial registration form.
- **Firm normalisation is string matching, not entity resolution.** It merges `KIRKLAND AND ELLIS
  LLP` into `KIRKLAND AND ELLIS`; it does not merge `SKADDEN ARPS` with the full firm name. The
  residual error is a small under-count at the low end.
- **Freshness is the publisher's, not ours.** The NYS Office of Court Administration's own metadata
  states a posting frequency of **Quarterly**; the file's `rowsUpdatedAt` read **2026-08-12T05:03:58Z**
  when this page was written, i.e. it had in fact been refreshed that morning. Every run logs the
  live timestamp so you can see the true age of the data you bought. Registration data is also
  inherently biennial — attorneys update their address when they re-register, not when they move.
- **`lastNames` is an exact match, not fuzzy.** `SMITH` will not return `SMITHERS` and a misspelled
  surname returns nothing. The run fails loudly rather than shipping an empty dataset.
- **No login, no API key, no CAPTCHA-solving service, and no attempt to touch the courts' own
  attorney-search web app.** This Actor reads one public open-data file.

### ⚙️ How it works (technical)

1. Reads `https://data.ny.gov/resource/eqw2-r5nb.json` — New York's public Socrata endpoint for the
   NYS Attorney Registrations dataset. No key, no auth, no browser.
2. Translates your inputs into one SoQL `$where` clause, so status, county, city, state and
   admission-year filtering all happen **on New York's servers**. A county × status slice costs a
   handful of requests instead of a 432,690-row download.
3. Asks for the match count first and refuses to start if it is zero, with a message naming what you
   asked for.
4. Sweeps `company_name` grouped by count (22 paged requests), normalises each name and builds the
   firm head-count map, then asserts the map looks sane — fewer than 1,000 distinct firms means the
   schema changed upstream and the run stops rather than shipping wrong head-counts.
5. Walks the result 5,000 rows at a time with `$order=registration_number` pinned. Socrata does not
   guarantee stable ordering across pages without it; without the pin, offset paging silently repeats
   and skips rows.
6. Normalises each record (phone to `(XXX) XXX-XXXX`, `"May 2028"` to `2028-05`), checks the
   registration number against the seen-set, applies `maxFirmSize`, and pushes in batches of 1,000
   with the charge attached to the push.

**Transport, measured through Apify:** direct, no proxy, **16/16 requests OK (100%) over 16,000 rows,
0 duplicates**. There is no anti-bot, no geo gate and no rate limit worth dodging on `data.ny.gov`,
which is why the proxy input defaults to off — the sibling Texas licence actor died on a proxy 590
while the direct request succeeded. Four runs on 2026-08-12/13 (1,000 rows on Apify, plus 1,000,
1,500 and a 93-row surname query locally) logged zero duplicate registration numbers between them.

### When a run fails

- **Zero matching rows** → the run throws with the filters you asked for and a reminder of the exact
  New York strings. It never green-lights an empty dataset.
- **A registration number not in the register** → throws naming the number. That *is* the answer.
- **The firm sweep returns fewer than 1,000 firms** → throws, on the assumption that New York changed
  the schema, rather than emitting rows with wrong head-counts.
- **Duplicate registration numbers** → skipped, counted and warned about in the log.
- Requests retry four times with backoff before the run gives up.

### ❓ FAQ

**Can I get attorney email addresses?**
No. New York publishes none, for any attorney, in this register — the file has 20 columns and email
is not one of them. You get phone on 100% of the default slice and a postal address on 93.1%.

**Is this the same as a bar-number lookup?**
Yes, and it is a first-class input. Paste registration numbers into `registrationNumbers` and you get
one row each with status, admission year, judicial department, firm and address. It searches every
status, so a disbarred or deceased attorney is returned rather than silently dropped.

**Can I verify a specific attorney by name?**
Set `lastNames` — an exact, case-insensitive surname match (BRODY returns 93 registrations across all
statuses). Clear `statuses` and `withContactOnly` first, or you will only see the currently-registered
ones with contact details. Filter to the right first name after export.

**How current is the data?**
The NYS Office of Court Administration states a quarterly posting frequency; the file's own
`rowsUpdatedAt` timestamp read 2026-08-12T05:03:58Z when this page was written. Every run logs that
timestamp, so you always know how old the data you just bought is.

**Why New York only?**
Because New York is the second-largest bar in the United States — 293,648 currently-registered
attorneys — and it is the one that publishes the whole register as a clean bulk open-data feed, which
is why this Actor can hand you 1,000 rows in seconds instead of hours of form-driving. Want another
state? Ask on the Issues tab. Florida was evaluated as the second source and rejected: The Florida
Bar's member profiles sit behind a Cloudflare interstitial (measured: HTTP 429 "Just a moment…" on
every profile fetch, including with a warmed session cookie), and its records carry a different field
set — bolting that on would mean shipping half-empty rows under a New York schema.

**Do I need a proxy?**
No. `data.ny.gov` is a public open-data API with no anti-bot and no geo gate; measured 16/16 requests
OK direct. The proxy field is there only if your account needs a fixed egress IP, and turning it on
adds a failure mode rather than removing one.

**Will I get duplicates? What about across two runs?**
Not within a run: the Actor pins `$order=registration_number` and checks each number against a
seen-set before pushing, so you are never billed twice for the same attorney. Across runs, dedupe on
`registrationNumber` at your end — it is stable and unique per attorney.

**How many rows can I get in one run?**
As many as `maxItems` allows; the whole default slice is 251,320 attorneys and the whole file is
432,690. There is no server-side result cap to work around — this is bulk open data, not a search
form that stops at 500.

**Do I get charged for rows that get filtered out?**
No. Status, geography and admission-year filters run on New York's servers so those rows are never
fetched, and `maxFirmSize` drops rows before the dataset write. You are billed per attorney
delivered, on push.

**Will a run ever succeed with zero rows?**
No. Zero matches throws with the scope you asked for. A green run with an empty dataset would be a
bug, not a result.

**Can I schedule it?**
Yes — use Apify Schedules. Registration data changes slowly (attorneys re-register biennially), so a
monthly or quarterly refresh is usually enough; check the freshness timestamp the run logs.

**Something looks wrong — how do I debug it?**
Read the run log. It prints the match count before it starts, the firm-sweep totals, the emitted
count per page, the upstream freshness timestamp, and the measured field fill for exactly the rows
you received. If those disagree with this page, open an issue.

### 💬 Support & 🔎 more scrapers

Missing a field, want another state, or need a filter that is not here? Open an issue on the
**Issues** tab of this Actor.

| Actor | What it is | Why you would use it instead |
|---|---|---|
| [California State Bar Attorney Scraper](https://apify.com/scrapersdelight/ca-attorney-scraper) | The California register — phone, firm, licence status | You need California, the largest US bar, from its own official source |
| This Actor | The New York register, plus a computed firm head-count | You need New York, bulk, with solo/small-firm targeting or a bar-number check |

We also build directory-side legal scrapers (Martindale-Hubbell peer ratings, Justia, Super Lawyers)
— see [our Apify profile](https://apify.com/scrapersdelight) for what is currently live. Those cover
marketing directories with ratings and practice areas; this Actor covers the licence register. If you
need practice areas or peer ratings, a directory scraper is the right tool; if you need licence
status and a bar number you can trust, this one is.

### ⚠️ Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by the New
York State Unified Court System, the New York State Office of Court Administration, the New York
State Bar Association, or any of their affiliates. All trademarks are the property of their
respective owners.

It reads a single public open-data file published by the NYS Unified Court System at `data.ny.gov`
under 22 NYCRR 118. It does not log in, does not solve CAPTCHAs, does not touch authenticated or
member-only endpoints, and collects no data that New York does not publish for public
licence-verification use.

Rows describe identifiable people. You are responsible for complying with New York's terms and with
how you use the data — including GDPR/CCPA where applicable, CAN-SPAM and telemarketing rules for
outreach, and the New York Rules of Professional Conduct on attorney advertising and solicitation
(Rules 7.1–7.3) if you are a law firm marketing to or through this list.

### SEO Keywords

new york state bar scraper, ny attorney registration search, new york attorney lookup, attorney
license verification, bar number lookup, lawyer license check api, attorney status check, ny bar
number search, new york lawyer directory scraper, attorney license lookup new york, nys attorney
registration data, lawyer lead generation new york, solo practitioner list, small law firm leads,
attorney contact list ny, law firm size data, legal lead generation scraper, attorney verification
api, disbarred attorney check, ny courts attorney search, new york bar admission year data, law
school alumni attorney list, attorney phone number list, legal tech icp data, malpractice insurance
leads, cle marketing list, attorney public records new york

# Actor input Schema

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

Which registration statuses to return. Counts are live rows in the New York file. Leave empty for all 432,690 registrations — which includes 49,199 deceased attorneys, so do that deliberately. Ignored when you look up a registration number in Step 2: a licence check always searches every status.

## `withContactOnly` (type: `boolean`):

Keep only records that carry a phone number or a street address. 251,320 of the 293,648 currently-registered attorneys (85.6%) do, and within that slice phone fill is 100%. With this off and all statuses on, the first 1,500 rows of a live run came back at 28.2% phone — so leaving it on is worth roughly 3.5x on every contact field. New York publishes NO email address for any attorney; phone and postal mail are the channels here. Ignored during a registration-number lookup.

## `registrationNumbers` (type: `array`):

New York attorney registration numbers, e.g. 1000629. Non-digits are stripped, so "No. 1000629" works. Returns one row per number with status, admission year, firm and address. If a number is not in the registry at all the run finishes with a NOT FOUND status message naming it — that is the verification answer, and you are not charged for it because no row was delivered.

## `lastNames` (type: `array`):

Exact surnames as New York publishes them, matched case-insensitively — e.g. BRODY returns 93 registrations across all statuses. Combine with a first-name check after export, or with the county and city filters below to narrow. This is an exact match, not a prefix or fuzzy match: SMITH will not return SMITHERS.

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

New York counties of the attorney's registered business address. Only 135,579 attorneys have a county — 53.9% of the 251,320-row default slice, and 46.2% of all 293,648 currently-registered attorneys — because the field is only populated for in-state addresses, so a county filter silently excludes every out-of-state attorney. Leave empty for everywhere.

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

Business-address cities, matched case-insensitively so you do not have to guess the casing New York used (the file holds both NEW YORK and New York). Largest: NEW YORK 73,613 + 3,803 · WASHINGTON 9,252 · BROOKLYN 5,530 · ALBANY 3,027 · BUFFALO 2,783 · WHITE PLAINS 2,646. Free text because there are thousands. Empty = all cities.

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

Two-letter state of the attorney's registered business address — New York attorneys practise everywhere. Currently-registered counts: NY 135,581 · NJ 12,834 · DC 10,557 · CA 10,119 · FL 6,222 · MA 4,318 · CT 4,315. 81,354 currently-registered rows carry no state at all, so this filter drops them. Empty = all states.

## `maxFirmSize` (type: `integer`):

Keep only attorneys whose firm has at most this many currently-registered New York attorneys. 1 = solo practitioners · 5 = solo and small firms, the ICP for every practice-management SaaS (115,242 attorneys measured 2026-08-12) · 20 = boutiques and below. Attorneys who list no firm at all are always kept — they are typically solos or in-house counsel. Leave empty to include BigLaw: Kirkland & Ellis alone has 1,242 registered New York attorneys.

## `admittedFromYear` (type: `integer`):

Only attorneys admitted in or after this year. Set it to the current year for the newly-admitted cohort — currently-registered counts are 2026: 4,988 · 2025: 9,763 · 2024: 7,117. Costs nothing extra: the filter runs server-side, so you fetch only the rows you are billed for.

## `admittedToYear` (type: `integer`):

Only attorneys admitted in or before this year. Use with the field above for a cohort (e.g. 2018-2020), or alone to find long-tenured attorneys for succession, retirement and law-firm M\&A outreach. The registry goes back to 1898.

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

Stop after this many attorneys. 1,000 = $3.00. The whole default slice (251,320 currently-registered attorneys with contact details) = $753.96. Rows dropped by your filters are never delivered and never charged.

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

Leave this off. data.ny.gov is New York's public open-data API: no key, no login, no anti-bot and no geo gate, measured at 16/16 requests OK direct from an Apify container. A proxy here only adds a failure mode. Set it only if your account needs a fixed egress IP.

## Actor input object example

```json
{
  "statuses": [
    "Currently registered"
  ],
  "withContactOnly": true,
  "counties": [
    "New York"
  ],
  "maxItems": 100
}
```

# Actor output Schema

## `items` (type: `string`):

One row per attorney registration: name, registration number, firm and firm head-count, phone, business address, county, law school, admission year and status.

# 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 = {
    "statuses": [
        "Currently registered"
    ],
    "counties": [
        "New York"
    ],
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapersdelight/state-bar-attorney-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 = {
    "statuses": ["Currently registered"],
    "counties": ["New York"],
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("scrapersdelight/state-bar-attorney-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 '{
  "statuses": [
    "Currently registered"
  ],
  "counties": [
    "New York"
  ],
  "maxItems": 100
}' |
apify call scrapersdelight/state-bar-attorney-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapersdelight/state-bar-attorney-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/czAmYyQNDQsuVTXAL/builds/zhAixDGOulMRek0Dq/openapi.json
