Justia Lawyer Profiles, Reviews & Office Locations Scraper avatar

Justia Lawyer Profiles, Reviews & Office Locations Scraper

Pricing

from $1.25 / 1,000 attorney results

Go to Apify Store
Justia Lawyer Profiles, Reviews & Office Locations Scraper

Justia Lawyer Profiles, Reviews & Office Locations Scraper

Scrape attorney profiles from the Justia Lawyer Directory. Extract names, contacts, office locations, practice areas, education, experience, awards, bar admissions, peer endorsements and Justia Lawyer Ratings. Search by state, city, practice area or scrape profile URLs.

Pricing

from $1.25 / 1,000 attorney results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

1

Bookmarked

3

Total users

0

Monthly active users

8 days ago

Last modified

Share

Justia Lawyer Directory Scraper: Attorney Profiles, Contacts & Ratings

Justia Lawyer Directory Scraper turns the Justia Lawyer Directory into a clean, structured attorney dataset. Get identity and contact details, multiple law offices with weekly hours, practice areas with sub-specialties, bar admissions with ID and admission year, education, awards, peer endorsements and the Justia Lawyer Rating breakdown, for attorneys across the United States. Search by state, practice area and city, or paste your own Justia directory, category or profile links, then export to JSON, CSV or Excel, or pull the results straight into your app through the API.

Why This Scraper?

  • Richest field set on the market. Every section Justia publishes: badges, biography, practice areas with sub-specialties, multiple offices with weekly hours, jurisdictions with bar ID and admission year, languages, education, professional experience, awards, associations, speaking engagements, certifications, publications, peer endorsements and the Justia Lawyer Rating breakdown.
  • Two ways to find attorneys. Search by state, practice area and city, or paste your own Justia directory, category or attorney profile URLs.
  • Filter before you pay for a profile fetch. Free consultation and top rated are checked on the listing card itself, before any profile page is opened, so a narrow filter never wastes a profile fetch.
  • Built for schedules. Incremental mode tracks one search or URL set over time and classifies every attorney NEW, UPDATED or UNCHANGED by default (EXPIRED and REAPPEARED need Emit expired too), so a recurring run returns and bills only what changed.
  • Resume without re-paying. Continue an interrupted run from its run or dataset ID, or let the actor recover on its own after a platform migration, with no duplicate records and no double charges.
  • Optional vCard enrichment. Turn on Fetch vCard to add a structured contact block (name parts, fax, organization, structured address) pulled from the attorney's own .vcf file.
  • Whole-catalogue runs. Max pages is unlimited by default; only Max results caps a run, so a full state or practice area can be walked in one go.

Use Cases

  • Legal lead generation: pull every attorney in a practice area and state to build outreach lists with phone numbers, offices and websites.
  • Legal marketing and SEO agencies: benchmark competitor firms' badges, ratings, biography copy and awards in a market.
  • Legal tech and directories: enrich or backfill your own attorney directory with structured practice areas, jurisdictions and education.
  • Referral networks: find top rated or free-consultation attorneys in a specific city for client referrals.
  • Market and compliance research: track new attorney entrants and rating changes in a practice area over time with Incremental mode.

Data You Get

Sample shape: values are illustrative placeholders, not from a live record.

FieldExample
type"profile"
id284001
url / profileUrl"https://lawyers.justia.com/lawyer/morgan-ellery-284001"
name"Morgan Ellery"
jobTitle"Personal Injury and Car Accident Lawyer"
primaryPhone / telephones"(415) 555-0142" / ["(415) 555-0142", "(415) 555-0177"]
justiaRating / topRated9.5 / false
ratingBreakdownLegal Knowledge, Legal Analysis, Communication Skills, Ethics and Professionalism (0 to 5 each); only filled when the profile page still shows those skill rows, which many profiles no longer do
yearsOfExperience15
badges["Claimed Lawyer Profile", "Offers Video Conferencing"]
biographymulti-paragraph biography text
practiceAreas[{ "area": "Personal Injury", "subAreas": ["Car Accidents", "Premises Liability"] }]
jurisdictions[{ "name": "California", "idNumber": "778899", "since": "2010" }]
education[{ "school": "Example State University College of Law", "degree": "J.D.", "endDate": "2009" }]
officesarray of { name, label, telephone, address, officeHours[] }, one entry per office
addressesevery office address, flattened to a single array
peerReviews[{ "reviewerName": "Reviewer Name", "rating": 9.0, "text": "..." }]
socialProfiles["https://www.linkedin.com/in/example-attorney/"]
websites["https://www.example-law-group.com"]
city / state"Oakland" / "CA"
freeConsultation / contingentFeestrue / true
emailContactUrl / vcardUrlcontact-form URL / vCard download URL
firstName / lastName / firmNameflat name parts and office name (profile rows carry the firm)
address / zip / phone / website / barAdmissionsflat convenience copies of the first office address, ZIP, primary phone, first website and bar jurisdiction names (profile rows only)
changeType"NEW" (also UPDATED, UNCHANGED, REAPPEARED, EXPIRED; Incremental mode only)

Rarer or secondary fields are also included when present: additionalPracticeAreas, videoConferencing, fees, languages, experience, associations, speakingEngagements, certifications, publications, videos, websiteDetails, breadcrumb, claimedProfile, offersVideoConferencing, connectPro, liiPlatinum, hasSocialMedia, clientReviewCount, the optional vcard block (only when Fetch vCard is on and that request landed), the Incremental-mode-only changedFields / firstSeenAt / lastSeenAt, and the run bookkeeping fields sourceUrl, scrapedAt and metadata. (faxNumbers and headerFacts exist as keys but are never currently populated by this actor. clientReviewRating is the profile's aggregate client rating on a 0-10 scale, when the profile shows one.) A directly pasted profile URL always returns the full record above except servingLocationText, which only comes from a listing card; a directory or search listing returns only the listing-card fields (type, id, url, name, telephones, freeConsultation, topRated, profileImage, profileUrl, slug, servingLocationText) unless Fetch full profile details is on.

How to Use

  1. Pick a mode: search (state, practice area, city filters) or url (paste Justia directory, category or profile links).
  2. Fill in the fields for that mode, and turn Fetch full profile details on for the richer record shape.
  3. Set Max results to control run size and cost, then click Start.
  4. Download the dataset as JSON, CSV or Excel, or read it through the API.

Search by state and practice area:

{
"mode": "search",
"states": ["California", "New York"],
"practiceAreas": ["Personal Injury", "Family Law"],
"fetchDetails": true,
"maxItems": 200
}

Drill into a city with a rating filter:

{
"mode": "search",
"states": ["Texas"],
"practiceAreas": ["DUI"],
"cities": ["Austin"],
"minRating": 8,
"fetchDetails": true,
"maxItems": 50
}

Paste profile URLs directly:

{
"mode": "url",
"startUrls": [
"https://lawyers.justia.com/lawyer/sample-attorney-100000",
"https://lawyers.justia.com/lawyer/sample-attorney-200000"
],
"fetchVcard": true
}

Monitor a whole state for changes on a schedule:

{
"mode": "search",
"states": ["Ohio"],
"practiceAreas": ["Family Law"],
"fetchDetails": true,
"maxItems": 0,
"incrementalMode": true,
"emitExpired": true,
"stateKey": "ohio-family-law-watch"
}

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/justia-lawyer-scraper").call(run_input={
"mode": "search",
"states": ["California"],
"practiceAreas": ["Personal Injury"],
"maxItems": 50
})
for attorney in client.dataset(run["defaultDatasetId"]).iterate_items():
print(attorney["name"], attorney.get("primaryPhone"))

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/justia-lawyer-scraper').call({
mode: 'search',
states: ['California'],
practiceAreas: ['Personal Injury'],
maxItems: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

Cost control

Two settings drive what a run costs: Fetch full profile details (each enriched attorney is billed once for the profile-enrichment event; listing-only runs are not) and Max results (the hard cap on records). Free consultation and top rated are checked on the card before any profile fetch, and an attorney rejected by Min rating is never pushed and never billed for enrichment, even though its profile page was opened to read the rating.

One exception worth knowing: pasting an attorney profile URL directly in url mode always opens and bills the full profile record, regardless of the Fetch full profile details setting. That toggle only controls whether directory or search listing results get enriched; a URL you named explicitly is always returned in full, and none of Free consultation only, Top rated only or Min rating are applied to it.

Resume and recurring updates

  • Resume (resumeFromRunId) continues one interrupted run: paste its run or dataset ID and the actor skips every attorney already collected there, so you don't pay twice. The actor also recovers on its own after a platform migration or the Resurrect button, with the same guarantee.
  • Incremental mode (incrementalMode) tracks one search or URL scope across scheduled runs. Each attorney is classified NEW, UPDATED (with changedFields), or UNCHANGED (suppressed and not billed unless emitUnchanged is on) by default. EXPIRED is only produced when emitExpired is on and that run's scan of the tracked search reached its natural end everywhere, uncapped by Max results or Max pages and not continued via Resume from run ID; a capped, resumed or partially-failed scan skips expiry detection for that run instead of guessing (in URL mode, a pasted profile URL that fails to load, or a Max results limit reached mid-walk, does not currently clear this signal, so treat the completeness guarantee as best effort for URL-mode runs with failures). REAPPEARED only ever fires for an attorney a prior such run had already marked EXPIRED, and never appears until that has happened once. Change detection compares every returned field except the run bookkeeping fields scrapedAt, sourceUrl, metadata and vcard, and ignores the order of plain lists (phone numbers, languages); extend that with ignoreFieldsForChanges. A start URL that begins at ?page=2 or later, a Max results or Max pages cap, or a shared State key used with rating or filter options never produces EXPIRED rows. stateKey names or shares one monitoring baseline; leave it empty to derive one automatically from your search and filter settings.

In URL mode with Start URLs left untouched, the actor scrapes two example directory listings (practice area plus state, the same listing form search mode reads) instead of nothing. The other shapes below are accepted as pasted links. Replace the list to scrape your own links. Links that are not Justia directory (with a state) or profile links are skipped with a warning in the log, and the run stops with a clear message if none are usable.

ShapeExample
Directory listing: practice area and statelawyers.justia.com/lawyers/personal-injury/california
Directory listing: state only, state plus city, or practice area plus state plus citylawyers.justia.com/lawyers/california, lawyers.justia.com/lawyers/personal-injury/california/los-angeles
Listing continued from a pagelawyers.justia.com/lawyers/personal-injury/california?page=2
Attorney profilelawyers.justia.com/lawyer/christopher-adamson-10198

A practice-area-only link such as lawyers.justia.com/lawyers/personal-injury is not a lawyer directory (Justia redirects it to a topic page), so the run skips it with a warning in the log; add a state.

In search mode, states accept a full name or 2-letter code (a state outside the known list, such as a territory, logs a warning and is still tried as a Justia directory name; DC, Washington DC and Washington, DC all map to the District of Columbia) and practice areas accept their display names.

Send results into your apps (MCP connectors)

Optionally pipe the scraped attorney records into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.

InputWhat it does
mcpConnectorsConnectors to send results to (Notion, Linear, Airtable or Apify). Authorize once under Apify, Settings, Integrations, then select it here. Leave empty to skip.
notionParentPageUrlNotion connector only: the page under which one page per attorney is created.
maxNotifyListingsCap on records written to each connector per run (default 50, max 1000). The dataset is not affected.

Each record is written as a condensed, human-readable summary (title plus key fields); the full record always stays in the dataset. The connection goes through Apify's MCP proxy, so this actor never sees your third-party credentials.

Input Parameters

ParameterTypeDefaultDescription
modestringsearchsearch (build a URL from the filters below) or url (paste Justia links).
statesarrayno default (prefill: ["California"])One or more US states (full name or 2-letter code). Search mode only.
practiceAreasarrayno default (prefill: ["Personal Injury"])One or more practice areas (e.g. "Personal Injury", "Criminal Law"). "All" or empty means no area filter. Search mode only.
citiesarrayno default (prefill: [])Optional city filter. Combines with each state. Search mode only.
startUrlsarraytwo example directory listings (supported shapes below)One or more Justia directory, category or attorney profile URLs. URL mode only.
fetchDetailsbooleantrueOpen each attorney's profile page to add badges, biography, offices, education, experience, awards, jurisdictions and the rating breakdown.
fetchVcardbooleanfalseAlso download the attorney's .vcf file to add a structured vCard block.
minRatingnumberno defaultOnly keep attorneys with at least this Justia Lawyer Rating (0 to 10). Only decidable when a profile is fetched.
freeConsultationOnlybooleanfalseOnly keep attorneys who advertise a free consultation.
topRatedOnlybooleanfalseOnly keep attorneys with the maximum Justia Lawyer Rating (10.0).
maxPagesinteger0Result pages read per directory URL. Does not cap the run; 0 = unlimited.
maxItemsinteger20The cap for the run: stop after this many attorney records (maximum 1,000,000). 0 = unlimited.
resumeFromRunIdstringno defaultPaste a previous run ID (or dataset ID) from this actor; attorneys already collected there are skipped.
incrementalModebooleanfalseTurn on for scheduled monitoring of the same search or URLs; returns only NEW and UPDATED attorneys by default (REAPPEARED needs Emit expired too, and a prior complete scan).
stateKeystringno defaultOptional. Name or share one monitoring baseline. Left empty, a key is derived automatically from your search and filter settings.
emitUnchangedbooleanfalseIncremental mode only. Also return (and bill) attorneys unchanged since the last run.
emitExpiredbooleanfalseIncremental mode only. Also return (and bill) attorneys no longer found, only after a complete scan of the tracked search.
ignoreFieldsForChangesarray[]Incremental mode only. Field names (or dotted paths such as peerReviews.date) left out of change detection. They are still returned, but never make an attorney UPDATED or appear in changedFields.
proxyobjectResidential (US)Network connection. Residential is the default and required for this site; it needs a paid Apify plan.
mcpConnectorsarray(none)Optional MCP connectors to send results to (see Send results into your apps).
notionParentPageUrlstringno defaultNotion connector only: the page under which attorney pages are created.
maxNotifyListingsinteger50Cap on records written to each connector per run; the dataset is not affected.

Output Example

Sample shape: values are illustrative placeholders, not from a live record.

{
"type": "profile",
"id": 284001,
"url": "https://lawyers.justia.com/lawyer/morgan-ellery-284001",
"profileUrl": "https://lawyers.justia.com/lawyer/morgan-ellery-284001",
"slug": "morgan-ellery",
"name": "Morgan Ellery",
"jobTitle": "Personal Injury and Car Accident Lawyer",
"primaryPhone": "(415) 555-0142",
"telephones": ["(415) 555-0142", "(415) 555-0177"],
"justiaRating": 9.5,
"topRated": false,
"ratingBreakdown": {
"Legal Knowledge": 5.0,
"Legal Analysis": 4.5,
"Communication Skills": 5.0,
"Ethics and Professionalism": 5.0
},
"yearsOfExperience": 15,
"badges": ["Claimed Lawyer Profile", "Offers Video Conferencing"],
"claimedProfile": true,
"offersVideoConferencing": true,
"freeConsultation": true,
"contingentFees": true,
"practiceAreas": [
{ "area": "Personal Injury", "subAreas": ["Car Accidents", "Premises Liability", "Wrongful Death"] }
],
"jurisdictions": [
{ "name": "California", "organization": "State Bar of California", "idNumber": "778899", "since": "2010" }
],
"education": [
{ "school": "Example State University College of Law", "degree": "J.D.", "endDate": "2009" }
],
"offices": [
{
"name": "Example Legal Group LLP",
"label": "Oakland Office",
"telephone": "(415) 555-0142",
"address": { "street": "200 Sample Plaza Suite 4", "city": "Oakland", "region": "CA", "postalCode": "94612", "country": "US" },
"officeHours": [{ "day": "Monday", "hours": "9:00 AM - 5:00 PM" }]
}
],
"peerReviews": [
{ "reviewerName": "Reviewer Name", "date": "June 4, 2024", "rating": 9.0, "text": "Thorough and responsive counsel throughout the case." }
],
"socialProfiles": ["https://www.linkedin.com/in/example-attorney/"],
"websites": ["https://www.example-law-group.com"],
"emailContactUrl": "https://lawyers.justia.com/lawyer/morgan-ellery-284001/contact",
"vcardUrl": "https://lawyers.justia.com/lawyer/morgan-ellery-284001/vcard",
"city": "Oakland",
"state": "CA",
"scrapedAt": "2026-09-29T12:00:00.000Z",
"sourceUrl": "https://lawyers.justia.com/lawyers/personal-injury/california"
}

Plan Requirement

This site sits behind a managed browser challenge: a plain request, including one through a residential proxy, only receives a "Just a moment..." interstitial with no listing content. Residential alone is therefore not enough. The actor clears the challenge automatically for each connection it uses and then reads the pages; you do not need to do anything, but it does need the Residential (US) proxy group, which is selected by default and requires a paid Apify plan. Leave Proxy at its default unless you supply your own working proxy URLs.

If the account's Apify proxy connection is refused (for example on an Apify free plan, which does not include proxy access) or no proxy access is available, the actor continues on a backup connection and logs: "The selected connection is unavailable to this run. Apify free plans do not include residential proxies." Pages served this way are logged as "Served over the backup connection", and some pages may still be unavailable. When nothing can be read the run fails with one of these messages instead of returning an empty dataset:

  • Proxy refused for the account and no backup connection left: "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required."
  • Proxy refused for the account and the backup connection also failed to load pages: "No results: residential proxies are unavailable on this run ... and the backup connection could not load the requested Justia pages."
  • Pages failed to load: "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search."

FAQ

How much does it cost?

This actor uses pay per event. You are charged for three events: Actor start (once per run), Dataset item (per attorney record returned) and Detail enrichment (per attorney whose full profile page was actually opened and returned, when Fetch full profile details is on). Listing-only runs skip the enrichment event; suppressed, unchanged and failed records are not billed. The Pricing tab shows the current rates. Use Max results to cap the cost of any run.

What output views are available?

The dataset has five views: Overview, Credentials, Reviews, Contact and Changes (incremental status and changedFields).

This actor collects only publicly available attorney directory information. You are responsible for how you use it: follow Justia's terms and the laws that apply to you, including any state bar rules on using contact information for attorney solicitation, and get legal advice if you plan commercial use of the data.

Can I get only new or changed attorneys on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new and updated records by default; unchanged ones are suppressed and not billed unless you turn on Emit unchanged, and reappeared records only show up once you also use Emit expired on an earlier complete scan.

Why does a pasted profile URL always come back fully enriched?

A directly pasted attorney profile link is the record you asked for by name, so the actor always opens and returns its full profile, and Free consultation only, Top rated only and Min rating are never applied to it. The Fetch full profile details toggle only changes behavior for directory or search listing results, where it decides whether each listed attorney's own profile page gets opened.

Why did my run fail instead of returning an empty dataset?

If a working connection cannot be established at all, or a resume ID cannot be resolved, the run stops with a clear failed status so a real problem is never mistaken for "no attorneys matched." If the connection works but a later page in the walk cannot be loaded, or your filters simply matched nobody, the run completes normally and the log (and run status message) says so.

Can I use it with AI agents or MCP?

Yes. Call this actor from any Apify integration, the API, or an MCP client connected to Apify, and read the resulting dataset into your own agent or workflow.

๐Ÿ”— Want more leads data?

Pair this actor with these related scrapers from the same team:

๐Ÿ“ฑ Clutch Scraper
Scrape Clutch company directories and profiles. Get names, ratings, review counts, hourly...
๐Ÿ“‡ TrueLocal AU Directory Listings & Reviews Scraper
Scrape TrueLocal.com.au business listings by keyword, location, or URL. Extract names...
๐Ÿ“‡ Yellow Pages NZ
Scrapes business listings from Yellow.co.nz (New Zealand Yellow Pages). Extract...
๐Ÿ“‡ Herold.at Scraper
Scrape Herold.at business listings across Austria into clean JSON. Extract names...
๐Ÿ  Real Estate AU Agents Scraper
Scrape Australian real estate agent and agency profiles by suburb or profile URLs...
๐Ÿ“‡ HiPages Scraper
Scrape business listings from HiPages Australia by category, location, or URL. Extract...

๐Ÿ‘‰ Browse all abotapi scrapers

๐Ÿ’ฌ Support

  • ๐Ÿž Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • ๐Ÿ› ๏ธ Need another site, extra fields or a private build? Email contact@abotapi.com.
  • โญ Enjoying it? A quick review on the actor page helps other users find it.