# Martindale Scraper - Attorney & Law Firm Leads (`scrapesage/martindale-scraper`) Actor

Scrape Martindale-Hubbell lawyer profiles: AV Preeminent Peer Review Rating, client reviews, practice areas, bar info, firm name, website & phone. Optional email enrichment & lead score. Search by city, practice area or URL. Export JSON, CSV, Excel.

- **URL**: https://apify.com/scrapesage/martindale-scraper.md
- **Developed by:** [Scrape Sage](https://apify.com/scrapesage) (community)
- **Categories:** Lead generation, Automation, Other
- **Stats:** 1 total users, 1 monthly users, 96.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$12.00 / 1,000 attorney leads

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/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

## Martindale Scraper — Attorney & Law Firm Leads (AV Preeminent Ratings, Reviews & Firm Contacts)

Extract **complete Martindale-Hubbell attorney data** — including the field every law-firm marketer wants: the proprietary **Martindale-Hubbell Peer Review Rating** (the famous **AV Preeminent** seal), client reviews, practice areas, years licensed, full firm contacts and geo. Optionally turn every attorney into a **ready-to-contact B2B lead** by crawling their firm's own website for **emails, phone numbers and social links**.

No login, no cookies, no browser — fast server-rendered extraction with a residential US proxy.

### Why this Martindale scraper?

Martindale-Hubbell has rated and reviewed US lawyers since 1868, and its **AV Preeminent Peer Review Rating** is the gold standard of attorney prestige. Most directory scrapers ignore it. This actor ships the **richest dataset in the category** — the listing card data *and* the full profile, merged:

| Data | Typical scrapers | This actor |
|---|---|---|
| Martindale-Hubbell **Peer Review Rating** + AV Preeminent badge | ❌ | ✅ |
| Client review rating + review count | ❌ | ✅ |
| Practice areas | partial | ✅ |
| Firm name + **firm website** + socials | ❌ | ✅ |
| All firm **phone numbers** + fax | partial | ✅ |
| Full address + map **geo** (lat/lng) | ❌ | ✅ |
| Years licensed / year admitted | ❌ | ✅ |
| Law school | ❌ | ✅ |
| Firm **contact emails** (from firm website) | ❌ | ✅ opt-in |
| Lead score (0–100) per attorney | ❌ | ✅ |
| Monitor mode — only NEW attorneys | ❌ | ✅ |

### Use cases

- **Legal lead generation** — attorneys and law firms are active buyers: legal tech & SaaS, case-management/CRM, e-discovery, malpractice & cyber insurance, lending, marketing, court reporting, expert-witness and staffing vendors all sell to them. Score by authority (`isAVPreeminent`, `peerReviewRating`, `reviewCount`) and reach them directly (`phone`, `website`, `enrichedEmails`).
- **Recruiting & business development** — find attorneys by city, practice area and seniority (`yearsLicensed`); build referral networks and lateral-hire lists.
- **Market & competitive intelligence** — map the lawyer landscape of any city/practice, track AV Preeminent density and firm footprints.
- **Co-counsel & referral sourcing** — pinpoint highly-rated specialists in a target market with verified firm contact data.
- **CRM enrichment** — append Peer Review Ratings, firm sites and practice areas to an existing attorney list via direct profile URLs.

### How to use

1. [Sign up for Apify](https://console.apify.com/sign-up) — the free plan is enough to try this actor.
2. Open the **Martindale Scraper**, enter locations and (optionally) practice areas, and click **Start**.
3. Watch results stream into the dataset table.
4. **Export** as JSON, CSV, Excel, XML, or RSS — or pull results programmatically via the [Apify API](https://docs.apify.com/api/v2).

### Input

```json
{
    "locations": ["Los Angeles, CA", "Houston, TX"],
    "practiceAreas": ["Personal Injury", "Family Law"],
    "maxResults": 100,
    "includeProfileDetails": true,
    "enrichEmails": false,
    "avPreeminentOnly": false,
    "monitorMode": false
}
```

- **locations** — where to search, as `City, ST` (`Los Angeles, CA`, `Houston, TX`, `New York, NY`) or `City, State`. Each location is combined with every practice area. Martindale results are city-scoped, so city-level locations give the best coverage.
- **practiceAreas** — filter by practice. Use a friendly term (`personal injury`, `family law`, `criminal defense`, `bankruptcy`, `estate planning`, `business law`, `real estate`, `immigration`, `divorce`, `DUI`, `employment`, `medical malpractice`, `tax`, `intellectual property`) or the exact Martindale name. Leave empty for **all** attorneys in each location.
- **startUrls** — direct Martindale URLs: attorney profiles (`/attorney/...`) or a searchlight results page. Used in addition to the locations.
- **maxResults** *(default 100)* — total attorney cap across all searches.
- **includeProfileDetails** *(default true)* — fetch each profile for firm website & socials, all phones + fax, address + geo, practice areas, law school, price range, review aggregate, Peer Review Rating label and bio. Turn off for a faster, listing-only run.
- **enrichEmails** *(default false)* — crawl each firm's own website (home + contact/about, up to 3 pages) for emails, phones and extra socials. Martindale never exposes emails — this is the only way to get them.
- **minPeerRating** / **avPreeminentOnly** / **minReviews** / **withPhoneOnly** / **withWebsiteOnly** — quality filters.
- **monitorMode** *(default false)* — emit only attorneys not seen in previous runs (see below).
- **proxyConfiguration** — keep the default **RESIDENTIAL US** proxy; Martindale blocks datacenter IPs.

### Output

One record per attorney:

```json
{
    "attorneyId": "2065760",
    "name": "Laura J. Portillo",
    "headline": "Family Law",
    "jobTitle": "Of Counsel",
    "profileUrl": "https://www.martindale.com/attorney/laura-j-portillo-2065760/",
    "imageUrl": "https://www.martindale.com/LBM_Images/Lawyers/lawyer-laura-portillo-photo-5207906.png",
    "peerReviewRating": 5,
    "peerReviewRatingLabel": "AV Preeminent",
    "isAVPreeminent": true,
    "clientReviewRating": 4.9,
    "reviewCount": 18,
    "yearsLicensed": 17,
    "admissionYear": 2009,
    "practiceAreas": ["Family Law", "Divorce", "Child Custody"],
    "schools": ["Loyola Law School"],
    "bio": "Laura Portillo focuses her practice on complex family law matters …",
    "firmName": "Law Offices of Michael Jay Berger",
    "firmUrl": "https://www.martindale.com/organization/law-offices-of-michael-jay-berger-1612386/",
    "website": "https://www.bankruptcypower.com",
    "phone": "310-299-1935",
    "phones": ["310-299-1935", "424-600-4850"],
    "street": "9454 Wilshire Blvd, Suite 600",
    "city": "Los Angeles",
    "state": "CA",
    "postalCode": "90212",
    "latitude": 34.0668,
    "longitude": -118.3998,
    "priceRange": "Fixed Hourly Rates",
    "offersVideoCalls": true,
    "isSubscriber": true,
    "enrichedEmails": ["info@bankruptcypower.com"],
    "leadScore": 92,
    "searchPracticeArea": "Family Law",
    "searchLocation": "Los Angeles, CA",
    "scrapedAt": "2026-06-23T12:00:00.000Z"
}
```

Fields are `null` only when the data genuinely doesn't exist (e.g. a free profile with no firm website), never because the scraper skipped them.

### Monitor mode — a steady feed of NEW attorneys

Turn on **monitorMode** to make every run remember the attorney IDs it has already returned (in a named key-value store) and emit only **new** attorneys next time. Combined with [Apify Schedules](https://docs.apify.com/platform/schedules) this gives you a clean drip of fresh leads with no duplicates.

It does **not** conflict with scheduling: the Schedule decides *when* the actor runs; monitor mode decides *which records* of that run are new. Use different `monitorStoreName` values to track independent searches separately.

### Automate & schedule

Run this actor on autopilot and pull results into your own stack:

- **[Apify API](https://docs.apify.com/api/v2)** — start runs, fetch datasets, manage schedules over REST.
- **[apify-client for JavaScript](https://docs.apify.com/api/client/js/)** and **[apify-client for Python](https://docs.apify.com/api/client/python/)** — official SDKs.
- **[Schedules](https://docs.apify.com/platform/schedules)** — run it hourly/daily/weekly to monitor a city or practice area for new attorneys; perfect for lead pipelines.
- **[Webhooks](https://docs.apify.com/platform/integrations/webhooks)** — trigger downstream actions (CRM import, Slack alert, email sequence) the moment a run finishes.

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

const client = new ApifyClient({ token: 'MY_APIFY_TOKEN' });

const run = await client.actor('scrapesage/martindale-scraper').call({
    locations: ['Los Angeles, CA'],
    practiceAreas: ['Personal Injury'],
    maxResults: 100,
    avPreeminentOnly: true,
    enrichEmails: true,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Got ${items.length} attorney leads`);
```

### Integrate with any app

Connect the dataset to 5,000+ apps — no code required:

- **[Make](https://docs.apify.com/platform/integrations/make)** — multi-step automation scenarios.
- **[Zapier](https://docs.apify.com/platform/integrations/zapier)** — push new attorney leads straight into your CRM.
- **[Slack](https://docs.apify.com/platform/integrations/slack)** — get notified when a monitored search finds new attorneys.
- **[Google Drive / Sheets](https://docs.apify.com/platform/integrations/drive)** — auto-export every run to a spreadsheet.
- **[Airbyte](https://docs.apify.com/platform/integrations/airbyte)** — pipe results into your data warehouse.
- **[GitHub](https://docs.apify.com/platform/integrations/github)** — trigger runs from commits or releases.

### Use with AI assistants (MCP)

The output is clean, LLM-ready JSON. You can call this actor from Claude, ChatGPT, or any agent framework through the **[Apify MCP server](https://docs.apify.com/platform/integrations/mcp)** — ask your assistant to "find AV Preeminent personal injury lawyers in Houston and list their firm contacts" and let it run this scraper for you.

### Build a complete US legal & B2B lead stack

Pair this with my other directory & lead-gen scrapers:

- **[Avvo Scraper](https://apify.com/scrapesage/avvo-scraper)** — Avvo Rating, client reviews & disciplinary status for the largest US attorney directory.
- **[FindLaw Scraper](https://apify.com/scrapesage/findlaw-scraper)** — lawyers & law firms from FindLaw.
- **[Super Lawyers Scraper](https://apify.com/scrapesage/superlawyers-scraper)** — Super Lawyers & Rising Stars selectees.
- **[Expertise.com Scraper](https://apify.com/scrapesage/expertise-scraper)** — vetted local professionals across verticals.
- **[Three Best Rated Scraper](https://apify.com/scrapesage/three-best-rated-scraper)** — top-3 hand-picked local businesses.
- **[Court Records Scraper](https://apify.com/scrapesage/court-records-scraper)** — case & docket data.
- **[TaxBuzz Scraper](https://apify.com/scrapesage/taxbuzz-scraper)** — accountants & tax professionals.
- **[LinkedIn Company Scraper](https://apify.com/scrapesage/linkedin-company-scraper)** — firmographics for the firms you find.
- **[Google Maps Scraper](https://apify.com/scrapesage/google-maps-scraper)** — local business leads with emails & phones.
- **[Website Contact Scraper](https://apify.com/scrapesage/website-contact-scraper)** — emails, phones & socials from any list of firm websites.

### Tips

- **City-level locations** give the best coverage — Martindale results are city-scoped. To exhaust a metro, add several cities and/or split by practice area.
- **AV Preeminent targeting**: set `avPreeminentOnly: true` for the highest-prestige attorneys only.
- **Cost control**: turn off `includeProfileDetails` for a fast listing-only pass (name, firm, city, phone, peer-review stars, AV badge), then re-run with profile details on a filtered shortlist.
- **Rate-limits**: keep the default residential proxy and a modest `maxConcurrency` (5). The actor automatically rotates to a fresh residential IP and retries on any Cloudflare challenge.

### FAQ

**How do I scrape Martindale lawyers for a specific city?** Put the city in `locations` as `City, ST` (e.g. `Los Angeles, CA`). Add `practiceAreas` to narrow by specialty, or leave it empty for every attorney in that city.

**What is the AV Preeminent Rating?** It's the top tier of the Martindale-Hubbell **Peer Review Rating** — lawyers rated by their peers for the highest levels of legal ability and ethical standards. This actor returns the rating label (`peerReviewRatingLabel`), the star value (`peerReviewRating`) and an `isAVPreeminent` flag.

**Where do the emails come from?** Never from Martindale (it doesn't publish emails). With `enrichEmails` on, the actor visits the attorney's own firm website and extracts publicly listed contact emails — the same thing a human visitor would see.

**Can I export to Google Sheets, CSV, or Excel?** Yes — one click in the dataset view, or automatically on every run via the [Google Drive integration](https://docs.apify.com/platform/integrations/drive).

**How do I get only new attorneys over time?** Turn on `monitorMode` and run on a [Schedule](https://docs.apify.com/platform/schedules). Each run emits only attorneys not seen before.

**A field is null — why?** Some attorneys genuinely don't publish a firm website, price range or reviews. Fields are `null` only when the data doesn't exist, not because the scraper skipped them.

**Is scraping Martindale legal?** This actor collects publicly available data only. You are responsible for using the data in compliance with applicable laws (GDPR/CCPA for personal data) and Martindale's terms.

### Need help?

Open an issue on the actor's **Issues** tab, or visit the [Apify help center](https://help.apify.com/). Feature requests are welcome — this actor is actively maintained.

# Actor input Schema

## `locations` (type: `array`):

Where to search, as <code>City, ST</code> (<code>Los Angeles, CA</code>, <code>Houston, TX</code>, <code>New York, NY</code>) or <code>City, State</code> (<code>Chicago, Illinois</code>). Each location is combined with every practice area below. Martindale results are city-scoped, so city-level locations give the best coverage. A bare state (<code>California</code>) is accepted best-effort.

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

Practice areas to filter by, combined with every location. Use a friendly term (<code>personal injury</code>, <code>family law</code>, <code>criminal defense</code>, <code>bankruptcy</code>, <code>estate planning</code>, <code>business law</code>, <code>real estate</code>, <code>immigration</code>, <code>divorce</code>, <code>DUI</code>, <code>employment</code>, <code>medical malpractice</code>, <code>workers compensation</code>, <code>tax</code>, <code>intellectual property</code>) or the exact Martindale practice-area name. Leave empty for ALL attorneys in each location.

## `startUrls` (type: `array`):

Direct Martindale URLs: attorney profiles (<code>https://www.martindale.com/attorney/jane-doe-esq-1234567/</code>) or a Martindale searchlight results page. Used in addition to the locations above.

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

Maximum number of attorney records to scrape across all locations and practice areas. Martindale is behind a Cloudflare challenge, so each page is loaded through a stealth browser — larger runs take longer.

## `includeProfileDetails` (type: `boolean`):

Fetch each attorney's profile page for the full record: firm website & socials, all phone numbers + fax, full address + map geo, practice areas, law school, price range, client/peer review aggregate, the Peer Review Rating label and bio. Turn off for a faster, lighter run that returns only the listing-level fields (name, firm, city, phone, peer-review stars, AV Preeminent badge, bio snippet).

## `enrichEmails` (type: `boolean`):

For each attorney that has a firm website, crawl it (home + contact/about, up to 3 pages) to extract contact emails, phone numbers and extra social links. Martindale itself never exposes emails — this is the only way to get them. Requires profile details.

## `minPeerRating` (type: `integer`):

Only keep attorneys whose Martindale-Hubbell Peer Review star rating is at least this value (e.g. 4 for highly-rated). 0 = no minimum.

## `avPreeminentOnly` (type: `boolean`):

Keep only attorneys who carry the top Martindale-Hubbell AV Preeminent Peer Review Rating (the highest tier). Great for premium B2B targeting.

## `minReviews` (type: `integer`):

Only keep attorneys with at least this many client reviews. 0 = no minimum. Requires profile details.

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

Skip attorneys that have no phone number.

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

Skip attorneys that have no firm website. Requires profile details.

## `monitorMode` (type: `boolean`):

Remember attorney IDs returned in previous runs (in a named key-value store) and emit only NEW attorneys on each run. Perfect with Apify Schedules for a steady new-lead feed — it does not conflict with scheduling: the schedule triggers the run, monitor mode deduplicates this run's records against everything earlier runs already returned.

## `monitorStoreName` (type: `string`):

Name of the key-value store that holds the seen-attorney memory for monitor mode. Use different names to track independent searches separately (lowercase letters, digits and hyphens only).

## `maxConcurrency` (type: `integer`):

How many Martindale pages to load in parallel through the stealth browser. 3 is a safe default; raise it (more memory/CPU) for speed or lower it if you hit rate-limits.

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

Proxies to use. A RESIDENTIAL US proxy is REQUIRED — Martindale fronts every page with a Cloudflare challenge that only clears from a residential US IP. The default is recommended.

## Actor input object example

```json
{
  "locations": [
    "Los Angeles, CA"
  ],
  "practiceAreas": [
    "Family Law"
  ],
  "maxResults": 50,
  "includeProfileDetails": true,
  "enrichEmails": false,
  "minPeerRating": 0,
  "avPreeminentOnly": false,
  "minReviews": 0,
  "withPhoneOnly": false,
  "withWebsiteOnly": false,
  "monitorMode": false,
  "monitorStoreName": "martindale-monitor",
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All scraped attorney lead records as JSON items in the default dataset.

# 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 = {
    "locations": [
        "Los Angeles, CA"
    ],
    "practiceAreas": [
        "Family Law"
    ],
    "maxResults": 50,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapesage/martindale-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 = {
    "locations": ["Los Angeles, CA"],
    "practiceAreas": ["Family Law"],
    "maxResults": 50,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapesage/martindale-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 '{
  "locations": [
    "Los Angeles, CA"
  ],
  "practiceAreas": [
    "Family Law"
  ],
  "maxResults": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call scrapesage/martindale-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

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