# Expert Witness Directory (`mambalabs/expert-witness-directory`) Actor

Expert witness and medico-legal directory records for the United States and Australia from 18 public sources, deduped into one record per person, mapped to one specialty taxonomy, with each source's terms posture disclosed.

- **URL**: https://apify.com/mambalabs/expert-witness-directory.md
- **Developed by:** [Mamba Labs](https://apify.com/mambalabs) (community)
- **Categories:** Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 expert records

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?

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

Pull expert witness and medico-legal directory records from United States and Australian sources into one deduped list. Each person gets one record, however many directories list them, with specialties mapped to one shared taxonomy and a published email only where a source prints one.

### Coverage today: United States and Australia

- The actor returns records for the **United States** and **Australia** only. It reads 18 sources: 7 in the US and 11 in Australia, counting ABIME once in the US.
- ABIME lists experts in several countries. The actor reads every ABIME listing and returns only its US and Australian records.
- UK and Canadian records are not offered. A `country` value other than `US` or `AU` stops the run with an error, and no UK or Canadian record is ever written to the dataset.
- The table below lists every US and Australian source with its status. "Implemented" sources parse live. "Planned (stub)" sources are recorded but not read yet. "Not covered" sources sit behind a bot challenge or a robots.txt block, and the actor does not read them.

### What it does

- Reads open directory pages, sitemaps, JSON endpoints, and PDFs.
- Filters by specialty, state, country, and source.
- Merges the same person across directories. A doctor on six panels comes back as one record with six sources.
- Maps every source's own specialty tags to one taxonomy, so "Forensic Psychiatry" and "Psychiatrist, general adult" filter together.
- Keeps records between runs in a named key-value store in your account. In feed mode a run returns only the experts that are new, changed, or removed since the last run.
- Optionally checks US physicians and psychologists against the free NPPES monthly file and adds the NPI.

### Sources and their terms

Read this table before you use the data. It gives the terms posture of every source as each source published it when the actor was built. Several sources publish terms that restrict automated collection, reproduction, commercial use, or soliciting the people they list. The actor reports the terms; it does not decide for you. Make your own call for your use case, and take legal advice where it matters.

| Source | Country | Access | Terms posture | Restricts | robots.txt | Email on page | Profiles | Status |
|---|---|---|---|---|---|---|---|---|
| [ABIME business directory](https://www.abime.org/business-directory/) | US, AU | Open (static-html) | none found; /terms-of-use/ returns 404 | none found | User-agent: \* Disallow: /wp-admin/ | some | 988 measured (112 Australia region) | Implemented |
| [LA Superior Court psychiatrist and psychologist panels (3 PDFs)](https://www.lacourt.org/division/criminal/pdf/psychiatrist.pdf) | US | Open (pdf) | none | none found | lacourt.org/robots.txt redirects to lacourt.ca.gov/robots.txt, which returned an empty body (measured 2026-09-30); the blob host has none | yes | 164 names and 175 emails measured (criminal panel, updated 2026-08-03) | Implemented |
| [SF Bar Register of Experts](https://www.sfbar.org/?post_type=roe) | US | Open (static-html) | none found (disclaimer and terms pages checked) | none found | robots.txt returns 200 with an empty body, nothing disallowed (measured 2026-09-30) | yes | 76 measured 2026-09-30; "over 600" claimed, stale | Implemented |
| [Contra Costa County Bar experts directory](https://www.cccba.org/?pg=experts-directory) | US | Open (static-html) | none found | none found | Disallow: /temp/ and quicksearch and Cloudflare challenge paths; Crawl-delay: 5 (measured 2026-09-30) | yes | 17 measured | Implemented |
| [Illinois State Bar expert directory](https://www.isba.org/experts) | US | Open (static-html) | none found | none found | disallows named crawlers (Baiduspider, Yandex, and others) only; the User-agent: \* groups are commented out or empty (measured 2026-09-30) | yes | 37 category pages measured; 30 to 60 listings estimated | Implemented |
| [Louisiana State Bar expert directory PDF](https://www.lsba.org/newsandpublications/expertwitness.aspx) | US | Open (pdf) | none found | none found | robots.txt returns a 404 page, so nothing is disallowed (measured 2026-09-30) | yes | about 27 advertisers, 20 emails measured | Implemented |
| [AAIMCO member directory (insurance consultants)](https://www.aaimco.com/) | US | Open (static-html) | not located | none found | Yoast default: User-agent: \* with an empty Disallow (measured 2026-09-30) | yes | 70 measured | Implemented |
| [LACBA expert4law](https://expert4law.org/?pg=expert4lawExpertDirectory) | US | Open (static-html) | LACBA disclaimer and proprietary notice bars reproduction | reproduction | none seen | yes | "more than 1,000" claimed | Planned (stub) |
| [Lexvisio](https://www.lexvisio.com/) | US | Open (static-html) | none explicit | none found | not restrictive | no | 2,153 measured | Planned (stub) |
| [Law.com Experts (ALM)](https://www.law.com/expert-witness/) | US | Open (static-html) | none explicit | none found | recorded by the recon, not restrictive for expert pages | no | "15,000+" claimed | Planned (stub) |
| [ExpertPages](https://www.expertpages.com/) | US | Disallowed by robots.txt (static-html) | bars republishing | reproduction, automation | User-agent: \* Disallow: / (only named search engines allowed) | no | 460 measured | Not covered: robots.txt disallows all non-search crawlers and no profile shows an email |
| [JurisPro](https://www.jurispro.com/) | US | Open (static-html) | Terms ban unauthorized scraping and separately ban soliciting listed experts by email, phone, text, or fax for other directories, referral services, or similar marketing | automation, solicitation | not restrictive | no | 1,962 measured | Planned (stub) |
| [Experts.com](https://www.experts.com/) | US | Open (static-html) | Terms bar use by scripts, machines, or automated services, and bar using information from the site for uninvited solicitations | automation, solicitation | recorded by the recon | yes | 748 measured | Planned (stub) |
| [TrialSmith expert index (names only)](https://www.trialsmith.com/) | US | Open (static-html) | Terms and Conditions bar reproduction | reproduction | recorded by the recon | no | 233,953 name pages measured | Not covered: name and deposition count only, many common-name collisions; kept as a possible verification join, not a record source |
| [SEAK expert witness directory](https://www.seakexperts.com/) | US | Blocked by bot defense (cloudflare) | no terms page located | none found | allows /members/ | unknown | "over 2,000" claimed | Not covered: Cloudflare challenge; no bypass without a separate decision (work order decision 4); Aaron declined a bypass on 2026-09-30 |
| [Expert Institute](https://www.expertinstitute.com/) | US | Blocked by bot defense (cloudflare) | not reached | none found | not reached | unknown | "1+ million" claimed | Not covered: Cloudflare challenge; no bypass without a separate decision (work order decision 4); profiles are auto-generated from public sources |
| [American Academy of Psychiatry and the Law](https://www.aapl.org/) | US | Blocked by bot defense (cloudflare) | not reached | none found | not reached (Cloudflare 403 on robots.txt) | unknown | not measured | Not covered: Cloudflare challenge; no bypass without a separate decision (work order decision 4) |
| [Medilaw](https://www.medilaw.com.au/) | AU | Open (static-html) | none found in the sitemap | none found | robots.txt returns HTTP 200 with an empty body (measured 2026-09-30) | panel-only | 214 measured 2026-09-30 | Implemented |
| [Lex Medicus](https://lexmedicus.com.au/) | AU | Open (static-html) | not located | none found | Disallow: /wp-admin/ and /?html2pdf=\* (measured 2026-09-30) | panel-only | 184 measured 2026-09-30 | Implemented |
| [Australian Specialist Hub](https://aushub.com.au/) | AU | Open (static-html) | not located | none found | User-agent: \* Disallow: (everything allowed) (measured 2026-09-30) | panel-only | 294 measured 2026-09-30 | Implemented |
| [Medico Legal Specialists](https://medicolegalspecialists.com.au/) | AU | Open (static-html) | not located | none found | User-agent: \* Disallow: (everything allowed) (measured 2026-09-30) | panel-only | 143 measured 2026-09-30 | Implemented |
| [Index Medicolegal](https://indexmedicolegal.com/) | AU | Open (static-html) | not located | none found | User-agent: \* Disallow: (allow all) (measured 2026-09-30) | panel-only | 110 measured 2026-09-30 | Implemented |
| [Themis Medico-Legal](https://themisml.com.au/) | AU | Open (static-html) | Terms s.4.3: "You must not copy, reproduce, modify, distribute, display, or exploit any content without our prior written consent." | reproduction, commercial-use | Disallow: /wp-admin/ (measured 2026-09-30) | panel-only | 82 measured | Implemented |
| [IntegrityML](https://integrityml.com.au/experts/) | AU | Open (json-api) | Disclaimer: no part "may be reproduced without the specific written permission ... except with appropriate attribution" | reproduction | User-agent: \* Disallow: (everything allowed; measured 2026-09-30) | panel-only | 57 measured | Implemented |
| [VERIFY Medico-Legal Solutions](https://vmls.com.au/) | AU | Open (static-html) | no scraping, automation, or reproduction clause found | none found | Disallow: /wp-admin/ (measured 2026-09-30) | panel-only | 25 measured | Implemented |
| [LIME Medicolegal](https://www.limeml.com.au/) | AU | Open (static-html) | no scraping or reproduction clause found | none found | sitemap line only (measured 2026-09-30) | panel-only | 25 measured | Implemented |
| [Medicolegal Assessments Group directory PDF](https://medicolegalassessmentsgroup.com.au/) | AU | Open (pdf) | none found | none found | blocks named downloaders (HTTrack, EmailCollector, and others) with Disallow: /; no User-agent: \* group (measured 2026-09-30) | no | about 486 measured by the recon | Implemented |
| [WorkCover WA approved medical specialists](https://www.workcover.wa.gov.au/) | AU | Open (json-api) | none found | none found | recorded by the recon, not restrictive | no | 310 measured 2026-09-30 (88 psychiatrists) | Implemented |
| [Specialists Medicolegal Australia](https://specialistsmedicolegalaustralia.com.au/) | AU | Open (static-html) | not located | none found | Disallow: (allow all) | panel-only | 28 measured | Planned (stub) |
| [Medibytes Legal](https://medibytes.com.au/our-panel/) | AU | Open (static-html) | Website terms PDF: "You must not conduct any systematic or automated data collection activities (including without limitation scraping, data mining, data extraction and data harvesting)"; also bars commercial exploitation | automation, commercial-use | Disallow: /wp-admin/ | panel-only | 22 measured | Planned (stub) |
| [NSW Personal Injury Commission medical assessors](https://www.pi.nsw.gov.au/about-us/medical-assessors-by-specialty) | AU | Open (static-html) | none found | none found | recorded by the recon | no | about 180 measured | Planned (stub) |
| [RANZCP Find a Psychiatrist (yourhealthinmind.org)](https://www.yourhealthinmind.org/find-a-psychiatrist) | AU | Open (js) | not checked by the recon | none found | User-agent: \* with sitemap only (no disallow) | some | not measured | Planned (stub) |
| [SIRA NSW permanent impairment assessors](https://www.sira.nsw.gov.au/information-search/permanent-impairment-assessors) | AU | Blocked by bot defense (cloudflare) | public government data | none found | not reached | unknown | not measured | Not covered: Cloudflare challenge; no bypass without a separate decision (work order decision 4); manual route for Proofed's own list |
| [WorkSafe Queensland register of permanent impairment trained assessors](https://www.worksafe.qld.gov.au/_media/tools/register-of-permanent-impairment-trained-assessors.xlsx) | AU | Blocked by bot defense (cloudflare) | public government data | none found | not reached | unknown | not measured | Not covered: Cloudflare challenge; no bypass without a separate decision (work order decision 4); manual route for Proofed's own list |
| [WorkSafe Tasmania accredited medical practitioners](https://worksafe.tas.gov.au) | AU | Blocked by bot defense (cloudflare) | site requires accepting terms before the list is shown | none found | not reached | unknown | not measured | Not covered: Cloudflare challenge; no bypass without a separate decision (work order decision 4); manual route for Proofed's own list |

#### Sources whose terms restrict commercial use, solicitation, automation, or reproduction

- **Themis Medico-Legal**: reproduction, commercial-use. Terms s.4.3: "You must not copy, reproduce, modify, distribute, display, or exploit any content without our prior written consent."
- **IntegrityML**: reproduction. Disclaimer: no part "may be reproduced without the specific written permission ... except with appropriate attribution"
- **LACBA expert4law**: reproduction. LACBA disclaimer and proprietary notice bars reproduction
- **ExpertPages**: reproduction, automation. bars republishing
- **JurisPro**: automation, solicitation. Terms ban unauthorized scraping and separately ban soliciting listed experts by email, phone, text, or fax for other directories, referral services, or similar marketing
- **Experts.com**: automation, solicitation. Terms bar use by scripts, machines, or automated services, and bar using information from the site for uninvited solicitations
- **TrialSmith expert index (names only)**: reproduction. Terms and Conditions bar reproduction
- **Medibytes Legal**: automation, commercial-use. Website terms PDF: "You must not conduct any systematic or automated data collection activities (including without limitation scraping, data mining, data extraction and data harvesting)"; also bars commercial exploitation

Sources marked "Blocked by bot defense" sit behind a Cloudflare challenge. This actor does not attempt to bypass bot challenges.

### Input

| Field | What it does |
|---|---|
| `specialty` | Taxonomy codes. A parent code matches its children. |
| `region` | State or region as the source prints it. |
| `country` | `US`, `AU`, or both. Empty returns both. |
| `sources` | Directories to read. Empty reads every implemented US and Australian source. |
| `mode` | `list` returns every matching expert. `feed` returns only new, changed, returned, and removed experts since the last run on the same persistent store. |
| `verifyNppes` | Checks US records against the NPPES monthly file. |
| `maxItems` | Caps output rows. 0 means no cap. |
| `persistStoreName` | Named key-value store that keeps records between runs. Reuse it for feed mode. |

### Output

One row per deduplicated person per run. A person on three directories is one row with three entries in `sources`. Main fields: `name`, `post_nominals`, `specialty_raw`, `specialty_mapped`, `jurisdiction`, `country`, `firm`, `practice_site`, `published_email`, `email_source`, `email_type`, `phone`, `listing_url`, `sources`, `consent_basis`, `consent_status`, `npi`, `nppes_status`, `change_type`.

The actor never guesses an email. `published_email` is empty unless a source page printed an address.

### Change feed

- A record is `changed` only when its content changes: name, post-nominals, specialty, jurisdiction, country, firm, practice site, email, or phone. A new sitemap date or a new directory that adds nothing is not a change.
- A listing is `removed` after 2 complete, unfiltered runs do not find it. So removals can first appear on the third run for the same store. A run capped by `maxItems`, narrowed by a filter, or hit by a fetch error never removes anything.
- A `removed` row is emitted only when the person has no listing left on any source.

### NPPES check

With `verifyNppes` on, each US record is matched to the NPPES file on last name, first name, and state, and confirmed by specialty. Only a single match counts as `verified`. More than one is `ambiguous`. NPPES carries no email, so the check never adds one. The extract covers physicians and psychologists from the newest monthly file (September 2026 when this was written).

### Pricing

Pay per event. You pay only for rows written to the dataset.

| Event | Price | Charged when |
|---|---|---|
| `expert-record` (base record) | 4.00 USD per 1,000 | One deduplicated expert row in list mode. |
| `expert-record` (change feed row) | 4.00 USD per 1,000, the base record rate | One new, changed, returned, or removed row in feed mode. Unchanged experts are not emitted in feed mode and cost nothing. |
| `email-found` | 10.00 USD per 1,000 | The row carries a published email. Removed rows never charge it. |
| `npi-verified` | 2.00 USD per 1,000 | A US row checked against NPPES, with `verifyNppes` on. |

The Actor start event is 0.00005 USD, charged by Apify once per run for each GB of memory.

### Consent columns

Two columns are set when a record is first stored and are never recomputed at send time.

- `consent_basis` comes from the country: `US-CAN-SPAM` for a US record and `AU-SPAM-ACT-inferred` for an Australian record.
- `consent_status` is `unreviewed`, `approved`, or `blocked`, and starts as `unreviewed`. The actor never approves anything. You review segments and flip them yourself.

These columns are a starting label for your own review, not legal advice.

### How duplicates merge

1. The same personal email merges two listings, when the last names agree. A shared inbox such as `reception@` never merges people.
2. The same name plus the same phone merges.
3. The same name plus the same practice website merges.
4. The same name plus the same country plus the same specialty family merges, for panels that print only a name, a specialty, and a state. It never merges when the two carry different personal emails or websites, never on an initial-only first name, and once two different people are known to share it, it merges nobody.

Names fold common nicknames first, so Bob Smith and Robert Smith compare as one name. A name alone never merges, because common names belong to different people.

### Limitations

- ABIME prints no country or region in its sitemap, so the actor reads every listing page and keeps the US and Australian records after. Expect about 988 page reads for a full ABIME pass at one request per 2 seconds per host.
- Australian panel sources print the panel's contact details, not the doctor's, so those records carry a name, specialty, and state but no email.
- Nickname folding covers common English short forms only. A name printed with a different spelling on two sources can still come back as two people.

Built by [Mamba Labs](https://apify.com/mambalabs).

# Actor input Schema

## `specialty` (type: `array`):

Taxonomy codes. A parent code also matches its children: medicine.psychiatry includes medicine.psychiatry.forensic. Empty returns every specialty.

## `region` (type: `array`):

State or region as the source prints it, for example Queensland, California, New South Wales. Case and accents are ignored. Empty returns every region.

## `country` (type: `array`):

United States and Australia today. Empty returns both.

## `sources` (type: `array`):

Directories to read. Empty reads every implemented source. Sources that are not implemented yet, or that the actor does not cover, are skipped and named in the RUN\_SUMMARY record.

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

list returns every matching expert. feed returns only experts that are new, changed, or returned since the last run on the same persistent store, plus removed rows; unchanged experts are not emitted and cost nothing. A listing counts as removed after 2 complete, unfiltered runs miss it.

## `verifyNppes` (type: `boolean`):

Check each US record against the free NPPES monthly file (name, state, and specialty). Adds npi and nppes\_status. NPPES carries no email. Charged per checked record.

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

Stop after this many output rows (one row per deduplicated expert). 0 means no cap. A capped run never marks listings as removed.

## `persistStoreName` (type: `string`):

Named key-value store in your account that keeps expert records between runs. Reuse the same name for feed mode.

## Actor input object example

```json
{
  "specialty": [],
  "region": [],
  "country": [],
  "sources": [
    "sfbar"
  ],
  "mode": "list",
  "verifyNppes": false,
  "maxItems": 10,
  "persistStoreName": "expert-witness-directory-store"
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `runSummary` (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 = {
    "sources": [
        "sfbar"
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("mambalabs/expert-witness-directory").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 = {
    "sources": ["sfbar"],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("mambalabs/expert-witness-directory").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 '{
  "sources": [
    "sfbar"
  ],
  "maxItems": 10
}' |
apify call mambalabs/expert-witness-directory --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mambalabs/expert-witness-directory"
        }
    }
}
```

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/LIpwlgfE3LaQBaXd4/builds/HaUAyqkBD4UHjs7iA/openapi.json
