# Avvo.com \[Only $1💰] Lawyer Directory Scraper (`memo23/avvo-scraper`) Actor

💰$1 per 1,000 results – No limits. Turn Avvo.com into a structured US-attorney dataset. Pull name, firm, phone, full address with real coordinates, practice areas, languages, credentials, awards, hourly rate, and star ratings from any listing or attorney URL. JSON or CSV out, billed per result.

- **URL**: https://apify.com/memo23/avvo-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Automation, Lead generation, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

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 a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## Avvo.com Lawyer Directory Scraper

**Turn Avvo.com into a structured US-attorney dataset.** Scrape every attorney profile from any Avvo listing URL — name, firm, telephone, full street address with real lat/long coordinates, practice areas, languages, bar credentials, memberships, awards, hourly rate, accepted payment methods, star rating with review count, plus a clean bio — straight out of the page. JSON or CSV out, no compute charge per run, just per result.

#### How it works

![How Avvo Scraper works](https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-avvo.png)

#### ✨ Why use this scraper?

Building a US legal-marketing list? Mapping competition by practice area + city? Need a clean attorney dataset without paying for a legal-vertical CRM seat?

- 🎯 **Two ways to start.** Paste any Avvo URL (listing or attorney profile) — that always wins. Or, with no URLs set, pick a **practice area + US state** from the dropdowns and the scraper synthesizes the listing URL for you.
- 🏛 **Real firm name, not the attorney name.** `firmName` is parsed from the rendered HTML masthead — most JSON-LD-only scrapers conflate it with the attorney's name (Avvo's `LocalBusiness.name` repeats the lawyer). We don't.
- ⚖️ **Avvo Rating (1-10 scale) + tier label.** `avvoRating: 9.7`, `avvoRatingLabel: "Superb"`, `avvoRatingType: "Good"` (trend) — Avvo's own algorithmic rating, distinct from the 5-point review-rating. Competitors often miss this entirely.
- 📊 **Practice areas with share percentages + descriptions.** Each `practiceAreas[]` row carries `name`, `share` ("30%"), AND a description — extracted from Avvo's rendered practice-area chart. `primaryPracticeArea` surfaces the top one as a flat string.
- 🎓 **Structured education + bar admissions with year.** `education[]` is `[{school, degree, year}]`. `barAdmissions[]` is `["California (2004)"]`. `licenses[]` carries the full breakdown (state, year, status, license_status, yearsLicensed).
- 📅 **Years of experience + claimed-profile flag.** `yearsOfExperience` derived from the longest active license. `claimedProfile`, `isPro`, `isAdvertiser`, and `disciplinaryAction` all parsed from Avvo's embedded payload + license-status text.
- 💰 **Fees in three flat fields.** `feeFreeConsultation` (boolean), `feeContingency` (boolean), `feeHourlyRate` ("$ 650-750 per hour") — pulled from the rendered Fees and Rates section.
- ⭐ **Reviews + endorsements split.** `rating` (5-pt JSON-LD), `reviewScore` (unrounded 4.802), `reviewCount`, `endorsementsReceived` (peer endorsements), `legalAnswersWritten` (Q&A activity) — Avvo packs both interaction types into one counter; we split them.
- 🏆 **Awards as `[{title, year}]`.** `"Super Lawyer - 2024"` becomes `{title: "Super Lawyer", year: "2024"}` — and multi-year award strings (e.g. `"Client's Choice - 2026,2025,2024"`) get exploded into one row per year.
- 📍 **Real coordinates, not just zip codes.** Each row carries `coordinates.latitude` + `coordinates.longitude` parsed straight from the JSON-LD `geo` block — drop attorneys onto a map without a geocoding step.
- 🌐 **`website` and `linkedin` separated.** First non-social URL goes to `website`, any LinkedIn URL goes to `linkedin` — the full `sameAs[]` array is preserved too.
- 🛡 **Cloudflare-aware, zero browser automation.** Three-stack TLS race (impit + got-scraping + curl-impersonate) handles the anti-bot layer without spinning up a headless Chromium.
- 📤 **Clean exports.** One row per attorney. No padding rows, no duplicate firm rows. JSON + CSV exported automatically.

#### 🎯 Use cases

| Team | What they build |
|------|-----------------|
| **Legal marketing / SaaS GTM** | Outbound lists for vendors selling to small/solo law firms — by state, city, and practice area |
| **Bar association researchers** | Coverage maps of attorney density per practice area across cities + states |
| **Lead-gen / referral networks** | Building local attorney directories or referral matchmaking by language, practice area, rating |
| **Competitive intelligence** | Competitor benchmarking — pricing (`priceRange`), reviews, awards, credentials |
| **Journalists / academic research** | Studies on legal-services access, language coverage, attorney concentration |
| **Existing platforms enriching their data** | Patching attorney records with verified phone, address, geo coords, and ratings |

#### 📥 Supported inputs

The scraper accepts inputs in two mutually-exclusive modes — **URLs take strict precedence over filters**:

> ⚠️ **Precedence rule.** If `startUrls` has any non-empty entry, the practice-area + state dropdowns are completely ignored. To use the dropdown filters, leave `startUrls` empty.

##### Mode 1 — Paste Avvo URLs (highest priority)

Drop one or more avvo.com URLs into `startUrls`. Each URL is classified automatically:

| URL pattern | Behaviour |
|---|---|
| `https://www.avvo.com/all-lawyers/{state}/{city}.html` | **Listing** — extracts attorney links + walks pagination |
| `https://www.avvo.com/{practice-area}-lawyer/{state}.html` | **Listing** — practice-area + state |
| `https://www.avvo.com/search/lawyer_search?q=...&loc=...` | **Listing** (search results) |
| `https://www.avvo.com/attorneys/{zip}-{state}-{slug}-{id}.html` | **Attorney detail** — routed straight to the profile parser |

Easiest workflow: apply your filters on avvo.com in the browser, copy the URL from the address bar, paste into `startUrls`.

##### Mode 2 — Practice area + US state dropdowns (used when `startUrls` is empty)

Both dropdowns are **multi-select**. Pick one or many of each:

- **Practice areas** — 14 options (`real-estate-lawyer`, `family-lawyer`, `criminal-defense-lawyer`, etc.)
- **U.S. states** — all 50 states + DC

The scraper expands the cartesian product. With 2 practice areas × 3 states the actor crawls 6 listings:

````

{real-estate-lawyer, family-lawyer} × {ca, ny, tx}
→ /real-estate-lawyer/ca.html
→ /real-estate-lawyer/ny.html
→ /real-estate-lawyer/tx.html
→ /family-lawyer/ca.html
→ /family-lawyer/ny.html
→ /family-lawyer/tx.html

````

Pagination is followed automatically on each listing until `Max items` is reached.

**Edge cases:**
- Practice area(s) selected, no states → national listings (e.g. `/real-estate-lawyer.html` for the whole US).
- States selected, no practice area → no synthesized URLs (Avvo's `/all-lawyers/{state}.html` is a city-picker page with no actual listings). A warning is printed; add a practice area or paste explicit URLs.

**Not supported:**

- Avvo Q&A pages, guides, and articles (the scraper targets attorney profiles only)
- Hosts outside `avvo.com` / `www.avvo.com`

#### 🔄 How it works

1. **Resolve start URLs.** Synthesize a listing URL from the practice-area + state dropdowns (if set) and combine with any pasted `startUrls`.
2. **Classify each URL** as a listing URL or a single attorney profile URL.
3. **Fetch each listing** and pull every attorney profile link from the page (~20 per listing page on Avvo).
4. **Follow pagination** by walking `?page=N` until either no `rel="next"` link exists or `maxItems` is reached.
5. **Fetch each attorney detail page** in parallel through a global sliding window.
6. **Parse the JSON-LD `LocalBusiness` block** for name, phone, full address, geo coordinates, languages, credentials, memberships, ratings, hourly rate, payment methods — plus the rendered HTML for `firmName`, `practiceAreas[]` with shares + descriptions, and `education[]`.
7. **Decode HTML entities** in the bio (Avvo ships `&amp;`/`&quot;` literally inside the JSON-LD `description`).
8. **Push one row per attorney** to the dataset and export `data.csv` + `data.json` at the end.

#### 🪶 Lite mode

Toggle `liteMode` on and the scraper extracts data directly from each listing page's embedded `Person` JSON-LD blocks — no per-attorney detail HTTP calls. Trade-off:

- **~20× faster + ~20× cheaper.** One listing fetch yields ~20 rows.
- **Smaller field set.** `name`, `jobTitle`, `firmName`, `streetAddress`, `addressLocality`, `addressRegion`, `postalCode`, `addressCountry`, `telephone`, `image`, `education[]` (basic), `awards[]` (basic). **Not in lite mode:** bio, geo coordinates, practice-area shares + descriptions, languages, credentials, memberships, services, area served, hourly rate, payment methods, ratings, endorsements, LinkedIn.

Use lite mode when you only need contact + firm data (typical lead-gen flow). Use full mode for the rich 40-field profile (typical CRM enrichment / market-intelligence flow).

#### ⚙️ Input parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `searchByCategory` | array (enum) | `["real-estate-lawyer"]` | Practice-area slugs to crawl (14 options). **Multi-select.** Combined with `searchByLocation` as a cartesian product. Empty array = no synthesis. |
| `searchByLocation` | array (enum) | `["wy"]` | US state codes to filter listings by (51 options including DC). **Multi-select.** Empty array = national listings (one per category). |
| `startUrls` | array | — | Optional avvo.com URLs to crawl directly. Listing pages, search-result pages, and direct attorney profile URLs are all supported. Mix freely with the dropdowns above. |
| `liteMode` | boolean | `false` | Skip per-attorney detail fetches; emit one row per card from the listing's `Person` JSON-LD. ~20× faster and ~20× cheaper, but smaller field set. |
| `maxItems` | integer | `1000` | Hard cap on attorneys collected. Listings paginate ~20 per page; this cap limits billing. |
| `maxConcurrency` / `minConcurrency` | integer | `10` / `1` | Parallel HTTP request limits. |
| `maxRequestRetries` | integer | `5` | Retries before a request is given up. |
| `proxy` | object | Apify residential, US | Proxy configuration. Avvo serves Cloudflare on detail pages — a US residential pool is strongly recommended. |

#### 📊 Output overview

Each scraped attorney is one **single dataset row** of `type: "attorney"`. There are no separate firm rows; firm name and address live on the attorney row, so the dataset row count equals the attorney count exactly.

#### 📦 Output sample

One row per attorney (trimmed to the most useful fields):

```json
{
    "type": "attorney",
    "attorneyId": "415841",
    "id": 415841,
    "url": "https://www.avvo.com/attorneys/85719-az-adam-weisman-415841.html",
    "profileUrl": "https://www.avvo.com/attorneys/85719-az-adam-weisman-415841.html",
    "name": "Adam Weisman",
    "firmName": "Hinderaker Rauh & Weisman, PLC",
    "bio": "Adam Weisman is a real estate, business, and construction lawyer and litigator based in Tucson, Arizona and Jackson Hole, Wyoming.",
    "bioSummary": "Adam Weisman is a real estate, business, and construction lawyer and litigator based in Tucson, Arizona and Jackson Hole, Wyoming.",
    "image": "https://images.avvo.com/avvo/ugc/images/head_shot/standard/lawyer_adam_weisman_415841_1588792397.jpg",
    "telephone": "+1 (520) 214-1122",
    "primaryPhone": "5202141122",
    "address": "2401 East Speedway, Tucson, AZ",
    "streetAddress": "2401 East Speedway",
    "addressLocality": "Tucson",
    "addressRegion": "AZ",
    "city": "Tucson",
    "state": "AZ",
    "postalCode": "85719",
    "addressCountry": "US",
    "coordinates": { "latitude": 32.236417, "longitude": -110.936529 },
    "specialties": ["Contracts & Agreements", "Real Estate", "Landlord & Tenant", "Litigation"],
    "practiceAreas": [
        { "name": "Real Estate", "share": "30%", "description": "Advice on all aspects of real estate law including contested matters, easements, property rights, evictions, and foreclosures." },
        { "name": "Landlord or Tenant", "share": "25%", "description": "Advice on and litigation of commercial and residential landlord and tenant issues." },
        { "name": "Litigation", "share": "25%", "description": "Civil litigation of business and real estate matters including property line disputes, easements, adverse possession, eviction, and foreclosure." },
        { "name": "Contracts and Agreements", "share": "20%", "description": "Review, interpretation, and drafting of leases, operating agreements, lending documents, settlement agreements, and other contracts; formation of limited liability companies." }
    ],
    "languages": ["French"],
    "credentials": ["Licensed Attorney - Wyoming", "Licensed Attorney - Arizona"],
    "memberships": ["State Bar of Arizona, Real Property Section"],
    "awards": [
        { "title": "Super Lawyer", "year": "2024" },
        { "title": "Best Lawyer", "year": "2023" },
        { "title": "Distinguished", "year": "2019" },
        { "title": "Client's Choice", "year": "2021" }
    ],
    "education": [
        { "school": "University of Arizona College of Law", "degree": "JD - Juris Doctor", "year": "2002" },
        { "school": "Harvard University", "degree": "PhD - Doctorate", "year": "1995" },
        { "school": "Oxford University", "degree": "M.Phil", "year": "1989" },
        { "school": "Columbia University", "degree": "BA - Bachelor of Arts", "year": "1985" }
    ],
    "services": [],
    "areaServed": ["Wyoming", "Arizona"],
    "website": "https://www.hrtucson.com",
    "linkedin": null,
    "priceRange": null,
    "currenciesAccepted": "USD",
    "paymentAccepted": null,
    "acceptedPaymentMethod": [],
    "aggregateRating": { "ratingValue": 4.7, "reviewCount": 36, "bestRating": 5, "worstRating": 1 },
    "rating": 4.7,
    "reviewCount": 36,
    "endorsementsReceived": 3,
    "legalAnswersWritten": 3,
    "sameAs": ["https://www.hrtucson.com"],
    "ogImage": "https://images.avvo.com/...",
    "scrapedAt": "2026-05-09T12:37:13.624Z"
}
````

#### 🗂 Key output fields

| Group | Fields |
|---|---|
| **Identifiers** | `type`, `attorneyId`, `id` (numeric form), `url` / `profileUrl`, `scrapedAt` |
| **Person** | `name`, `firstName`, `lastName`, `firmName` (HTML-parsed, distinct from name), `bio` (full, decoded), `bioSummary` (first sentence), `image`, `claimedProfile`, `isPro`, `isAdvertiser` |
| **Contact** | `telephone` (formatted), `primaryPhone` (digits-only 10-digit form), `address` (composed), `streetAddress`, `addressLocality` / `city`, `addressRegion` / `state`, `postalCode`, `addressCountry`, `coordinates.{latitude,longitude}` |
| **Practice** | `primaryPracticeArea`, `specialties[]` (flat names), `practiceAreas[].{name, share, description}` (HTML-parsed with %-shares + descriptions), `languages[]`, `services[]`, `areaServed[]`, `memberships[]` (bar associations) |
| **Licensing** | `barAdmissions[]` (e.g. `["California (2004)"]`), `licenses[].{state, acquiredYear, status, licenseStatus, yearsLicensed}`, `credentials[]` (legacy JSON-LD form), `yearsOfExperience`, `disciplinaryAction` (boolean) |
| **Education / awards** | `education[].{school, degree, year}` (HTML-parsed), `awards[].{title, year}` (split + multi-year-aware) |
| **Web presence** | `website` (first non-social URL), `linkedin` (LinkedIn URL if present), `sameAs[]` (full outbound link list) |
| **Fees / commercials** | `feeFreeConsultation` (bool), `feeContingency` (bool), `feeHourlyRate` (e.g. `"$ 650-750 per hour"`), `priceRange` (legacy JSON-LD), `currenciesAccepted`, `paymentAccepted`, `acceptedPaymentMethod[]` |
| **Social proof** | `avvoRating` (10-pt Avvo Rating), `avvoRatingLabel` (`"Superb"`, `"Excellent"`, ...), `avvoRatingType` (trend), `rating` (5-pt review), `reviewScore` (unrounded), `reviewCount`, `aggregateRating.{ratingValue,reviewCount,bestRating,worstRating}`, `endorsementsReceived`, `legalAnswersWritten` |

#### ❓ FAQ

**Which Avvo URLs are supported?**
Listing URLs (`/all-lawyers/{state}/{city}.html`, `/{practice-area}-lawyer/{state}.html`, `/search/lawyer_search?...`) and direct attorney profile URLs (`/attorneys/{zip}-{state}-{slug}-{id}.html`). Avvo's Q\&A pages, legal guides, and any host outside `avvo.com` are skipped.

**Do I have to paste a URL or can I just pick from dropdowns?**
Either works, but **URLs take strict precedence**. If `startUrls` has any entry, the practice-area + state dropdowns are completely ignored (a warning is printed in the run log). To use the dropdowns, leave `startUrls` empty — the scraper will then synthesize `https://www.avvo.com/{practice-area}-lawyer/{state}.html` automatically.

**When should I enable `liteMode`?**
Enable it for cheap, large-scale lead-gen runs where you only need contact + firm data. One listing fetch yields ~20 rows (~20× faster and cheaper than full mode). Disable it for CRM enrichment, market intelligence, or any workflow that needs practice-area shares, ratings, endorsements, education, or full bios — those fields require fetching each attorney's detail page individually.

**Why is `firmName` different from the JSON-LD `name`?**
Avvo's `LocalBusiness` JSON-LD packs the attorney's own name into `name` (so the JSON-LD `name` field is the lawyer, not the firm). The real firm — `Hinderaker Rauh & Weisman, PLC` for Adam Weisman — is rendered in HTML, not JSON-LD. We parse the HTML so `firmName` always reflects the actual firm.

**What's `practiceAreas[].share`?**
Avvo renders a pie chart on each profile showing how the attorney splits their practice (e.g. `30%` real estate, `25%` litigation). Each `practiceAreas[]` row carries that percentage as a string (`"30%"`) plus a description. If the attorney didn't fill in shares, you get `share: null`.

**Why are some bios very long and others empty?**
The bio comes from the JSON-LD `description` field. Some attorneys have written extensive bios, others left it blank — the scraper passes through whatever the page provides. `bioSummary` is just the first sentence (capped at 280 chars), useful as a tagline.

**What's `endorsementsReceived` vs `legalAnswersWritten`?**
Avvo packs two distinct interaction counts into the same JSON-LD `interactionStatistic` array — peer endorsements (`EndorseAction`) and legal questions answered (`WriteAction`). Most scrapers either sum them or only surface the total; we split them so you can rank attorneys by peer reputation vs Q\&A activity separately.

**What's `priceRange` and how is it formatted?**
It's the hourly rate as Avvo displays it on the profile (e.g. `"$525/hr"`, `"$300/hr"`). Many attorneys leave it blank — those rows get `priceRange: null`.

**Why is my run getting blocked?**
Avvo serves Cloudflare on attorney detail pages. The scraper's three-stack TLS race (impit + got-scraping + curl-impersonate) handles that without browser automation, but if you turn off the proxy you may still see 403s — keep the default `RESIDENTIAL` + `country: US` proxy on.

**Can I scrape private pages or recruiter-only views?**
No. The scraper accesses only publicly available attorney profiles and listings — no logged-in content, no Avvo Pro / recruiter content, no candidate data.

**How do I limit results?**
Set `maxItems`. The actor stops queuing new attorneys as soon as the cap is reached.

#### 💬 Support

- For issues or feature requests, please use the **Issues** tab on the actor's Apify Console page.
- Author's website: <https://muhamed-didovic.github.io/>
- Email: <muhamed.didovic@gmail.com>

#### 🛠 Additional services

- Custom output shape, additional fields, or one-off datasets: <muhamed.didovic@gmail.com>
- Need a similar scraper for another legal directory (Justia, Martindale, FindLaw, Lawyers.com, Super Lawyers)? Drop an email.
- For API access (no Apify fee, just a usage fee for the API): <muhamed.didovic@gmail.com>

#### 🔎 Explore more scrapers

If this Avvo Scraper was useful, see other scrapers and actors at [memo23's Apify profile](https://apify.com/memo23) — covering job boards, real estate, social media, and more.

***

### ⚠️ Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Avvo, Internet Brands, or any of their subsidiaries or affiliates. All trademarks mentioned are the property of their respective owners.

The scraper accesses only publicly available attorney profile and listing pages on avvo.com — no authenticated endpoints, no Avvo Pro / recruiter-only features, and no content behind a logged-in session. Users are responsible for ensuring their use complies with avvo.com's Terms of Service, applicable data-protection law (GDPR, CCPA, etc.), and any state-bar rules around the marketing or use of attorney data in their jurisdiction.

***

### SEO Keywords

avvo scraper, scrape avvo, avvo api, avvo.com scraper, Apify avvo, us lawyer directory scraper, attorney directory scraper, lawyer data api, attorney data extraction, lawyer leads scraper, legal marketing leads, attorney contact data, lawyer contact info scraper, us attorney database, lawyer search api, legal directory scraper, legal vertical lead generation, justia alternative scraper, martindale alternative scraper, findlaw alternative scraper, super lawyers alternative scraper, lawyers.com alternative scraper, attorney email scraper, law firm scraper, solo practitioner data, small law firm leads, attorney practice areas data, lawyer ratings dataset, attorney star ratings api, attorney bar credentials data, attorney languages spoken data, lawyer geo coordinates, attorney hourly rate data, lawyer pricing data

# Actor input Schema

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

Paste any avvo.com URL — listing pages (`/all-lawyers/{state}/{city}.html`, `/{practice-area}-lawyer/{state}.html`, `/search/lawyer_search?...`) and direct attorney URLs (`/attorneys/{zip}-{state}-{slug}-{id}.html`) are auto-classified. Takes precedence over the practice-area + state filters below — clear this list to use the dropdowns.

## `searchByCategory` (type: `array`):

Select one or more practice areas. Combined with U.S. states below as a cartesian product (e.g. 2 areas × 3 states = 6 listing URLs). ⚠️ Ignored when the Avvo URLs field above is non-empty.

## `searchByLocation` (type: `array`):

Select one or more U.S. states. Combined with practice areas above as a cartesian product. Has no effect on its own — Avvo doesn't expose a useful state-only listing without a practice area. ⚠️ Ignored when the Avvo URLs field is non-empty.

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

Hard cap on the number of attorney profiles collected across all listings. Avvo listings paginate roughly 20 attorneys per page; the scraper follows pagination automatically until this cap is hit.

## `liteMode` (type: `boolean`):

When enabled, the scraper skips per-attorney detail fetches and emits one row per card directly from the listing page's embedded `Person` JSON-LD. ~20× faster and ~20× cheaper. Trade-off: rows have name + jobTitle + firmName + address + phone + image only. Disable to get the full 55+ field profile (Avvo Rating, practice-area shares, education, bar admissions with year, fees, claimed-profile flag, endorsements, awards split into title+year, etc.).

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

Maximum number of attorney detail pages processed in parallel.

## `minConcurrency` (type: `integer`):

Minimum number of attorney detail pages processed in parallel.

## `maxRequestRetries` (type: `integer`):

Number of retries before a failed request is given up.

## `proxy` (type: `object`):

Apify proxy settings. Avvo serves Cloudflare on attorney detail pages — a US residential pool is strongly recommended.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.avvo.com/all-lawyers/ca/los_angeles.html"
  ],
  "searchByCategory": [
    "real-estate-lawyer"
  ],
  "searchByLocation": [
    "wy"
  ],
  "maxItems": 1000,
  "liteMode": false,
  "maxConcurrency": 10,
  "minConcurrency": 1,
  "maxRequestRetries": 5,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# 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 = {
    "startUrls": [
        "https://www.avvo.com/all-lawyers/ca/los_angeles.html"
    ],
    "searchByCategory": [
        "real-estate-lawyer"
    ],
    "searchByLocation": [
        "wy"
    ],
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/avvo-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 = {
    "startUrls": ["https://www.avvo.com/all-lawyers/ca/los_angeles.html"],
    "searchByCategory": ["real-estate-lawyer"],
    "searchByLocation": ["wy"],
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/avvo-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 '{
  "startUrls": [
    "https://www.avvo.com/all-lawyers/ca/los_angeles.html"
  ],
  "searchByCategory": [
    "real-estate-lawyer"
  ],
  "searchByLocation": [
    "wy"
  ],
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call memo23/avvo-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Avvo.com [Only $1💰] Lawyer Directory Scraper",
        "description": "💰$1 per 1,000 results – No limits. Turn Avvo.com into a structured US-attorney dataset. Pull name, firm, phone, full address with real coordinates, practice areas, languages, credentials, awards, hourly rate, and star ratings from any listing or attorney URL. JSON or CSV out, billed per result.",
        "version": "0.0",
        "x-build-id": "Sd4bBJcjYGYJykduZ"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/memo23~avvo-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-memo23-avvo-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/memo23~avvo-scraper/runs": {
            "post": {
                "operationId": "runs-sync-memo23-avvo-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/memo23~avvo-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-memo23-avvo-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "startUrls": {
                        "title": "Avvo URLs",
                        "type": "array",
                        "description": "Paste any avvo.com URL — listing pages (`/all-lawyers/{state}/{city}.html`, `/{practice-area}-lawyer/{state}.html`, `/search/lawyer_search?...`) and direct attorney URLs (`/attorneys/{zip}-{state}-{slug}-{id}.html`) are auto-classified. Takes precedence over the practice-area + state filters below — clear this list to use the dropdowns.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "searchByCategory": {
                        "title": "Practice areas",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Select one or more practice areas. Combined with U.S. states below as a cartesian product (e.g. 2 areas × 3 states = 6 listing URLs). ⚠️ Ignored when the Avvo URLs field above is non-empty.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "bankruptcy-debt-lawyer",
                                "consumer-protection-lawyer",
                                "government-lawyer",
                                "business-lawyer",
                                "immigration-lawyer",
                                "intellectual-property-lawyer",
                                "criminal-defense-lawyer",
                                "lawsuits-disputes-lawyer",
                                "personal-injury-lawyer",
                                "employment-labor-lawyer",
                                "estate-planning-lawyer",
                                "family-lawyer",
                                "real-estate-lawyer",
                                "civil-rights-lawyer"
                            ],
                            "enumTitles": [
                                "Bankruptcy and debt",
                                "Consumer protection",
                                "Government",
                                "Business",
                                "Immigration",
                                "Intellectual property",
                                "Criminal defense",
                                "Lawsuits and disputes",
                                "Personal injury",
                                "Employment and labor",
                                "Estate planning",
                                "Family",
                                "Real estate",
                                "Civil rights"
                            ]
                        }
                    },
                    "searchByLocation": {
                        "title": "U.S. states",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Select one or more U.S. states. Combined with practice areas above as a cartesian product. Has no effect on its own — Avvo doesn't expose a useful state-only listing without a practice area. ⚠️ Ignored when the Avvo URLs field is non-empty.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "al",
                                "ak",
                                "az",
                                "ar",
                                "ca",
                                "co",
                                "ct",
                                "de",
                                "dc",
                                "fl",
                                "ga",
                                "hi",
                                "id",
                                "il",
                                "in",
                                "ia",
                                "ks",
                                "ky",
                                "la",
                                "me",
                                "md",
                                "ma",
                                "mi",
                                "mn",
                                "ms",
                                "mo",
                                "mt",
                                "ne",
                                "nv",
                                "nh",
                                "nj",
                                "nm",
                                "ny",
                                "nc",
                                "nd",
                                "oh",
                                "ok",
                                "or",
                                "pa",
                                "ri",
                                "sc",
                                "sd",
                                "tn",
                                "tx",
                                "ut",
                                "vt",
                                "va",
                                "wa",
                                "wv",
                                "wi",
                                "wy"
                            ],
                            "enumTitles": [
                                "Alabama",
                                "Alaska",
                                "Arizona",
                                "Arkansas",
                                "California",
                                "Colorado",
                                "Connecticut",
                                "Delaware",
                                "Dist. of Columbia",
                                "Florida",
                                "Georgia",
                                "Hawaii",
                                "Idaho",
                                "Illinois",
                                "Indiana",
                                "Iowa",
                                "Kansas",
                                "Kentucky",
                                "Louisiana",
                                "Maine",
                                "Maryland",
                                "Massachusetts",
                                "Michigan",
                                "Minnesota",
                                "Mississippi",
                                "Missouri",
                                "Montana",
                                "Nebraska",
                                "Nevada",
                                "New Hampshire",
                                "New Jersey",
                                "New Mexico",
                                "New York",
                                "North Carolina",
                                "North Dakota",
                                "Ohio",
                                "Oklahoma",
                                "Oregon",
                                "Pennsylvania",
                                "Rhode Island",
                                "South Carolina",
                                "South Dakota",
                                "Tennessee",
                                "Texas",
                                "Utah",
                                "Vermont",
                                "Virginia",
                                "Washington",
                                "West Virginia",
                                "Wisconsin",
                                "Wyoming"
                            ]
                        }
                    },
                    "maxItems": {
                        "title": "Max items",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Hard cap on the number of attorney profiles collected across all listings. Avvo listings paginate roughly 20 attorneys per page; the scraper follows pagination automatically until this cap is hit.",
                        "default": 1000
                    },
                    "liteMode": {
                        "title": "Lite mode (~20× faster, ~20× cheaper — name + firm + phone + address only)",
                        "type": "boolean",
                        "description": "When enabled, the scraper skips per-attorney detail fetches and emits one row per card directly from the listing page's embedded `Person` JSON-LD. ~20× faster and ~20× cheaper. Trade-off: rows have name + jobTitle + firmName + address + phone + image only. Disable to get the full 55+ field profile (Avvo Rating, practice-area shares, education, bar admissions with year, fees, claimed-profile flag, endorsements, awards split into title+year, etc.).",
                        "default": false
                    },
                    "maxConcurrency": {
                        "title": "Max concurrency",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Maximum number of attorney detail pages processed in parallel.",
                        "default": 10
                    },
                    "minConcurrency": {
                        "title": "Min concurrency",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Minimum number of attorney detail pages processed in parallel.",
                        "default": 1
                    },
                    "maxRequestRetries": {
                        "title": "Max request retries",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Number of retries before a failed request is given up.",
                        "default": 5
                    },
                    "proxy": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Apify proxy settings. Avvo serves Cloudflare on attorney detail pages — a US residential pool is strongly recommended.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ],
                            "apifyProxyCountry": "US"
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
