{
  "openapi": "3.0.1",
  "info": {
    "title": "Justia Lawyer Profiles, Reviews & Office Locations Scraper",
    "description": "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.",
    "version": "1.1",
    "x-build-id": "LaWsitOgyEkmkqsDa"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/abotapi~justia-lawyer-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-abotapi-justia-lawyer-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/abotapi~justia-lawyer-scraper/runs": {
      "post": {
        "operationId": "runs-sync-abotapi-justia-lawyer-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/abotapi~justia-lawyer-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-abotapi-justia-lawyer-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",
        "required": [
          "mode"
        ],
        "properties": {
          "mode": {
            "title": "Mode",
            "enum": [
              "search",
              "url"
            ],
            "type": "string",
            "description": "How to start the scrape. 'search' builds a directory URL from the state(s), practice area(s), and city below. 'url' takes the exact Justia directory or profile URLs you paste.",
            "default": "search"
          },
          "states": {
            "title": "State(s)",
            "type": "array",
            "description": "One or more US states (full name like 'California' or 2-letter code like 'CA'). Leave empty for all states. Applied as a search filter in search mode only.",
            "items": {
              "type": "string"
            }
          },
          "practiceAreas": {
            "title": "Practice area(s)",
            "type": "array",
            "description": "One or more practice areas (e.g. 'Personal Injury', 'Criminal Law', 'Family Law'). 'All' or empty means no area filter. Applied as a search filter in search mode only.",
            "items": {
              "type": "string"
            }
          },
          "cities": {
            "title": "City(s)",
            "type": "array",
            "description": "Optional city filter (e.g. 'San Francisco'). Combines with each state in search mode. Leave empty to scrape the entire state.",
            "items": {
              "type": "string"
            }
          },
          "startUrls": {
            "title": "Justia directory or profile URLs",
            "type": "array",
            "description": "Paste one or more Justia URLs (directory listing like https://lawyers.justia.com/lawyers/personal-injury/california, category, or attorney profile like https://lawyers.justia.com/lawyer/christopher-adamson-10198). Supported shapes: directory listing (state, state plus city, practice area plus state, practice area plus state plus city), listing with ?page=N, and attorney profile. A practice-area-only link (no state) returns no lawyers and is skipped with a warning, so add a state. Other links are skipped with a warning. Multi-URL supported. Filter fields above are ignored in URL mode. If a URL already includes a page number, results continue from that page.",
            "default": [
              "https://lawyers.justia.com/lawyers/personal-injury/california",
              "https://lawyers.justia.com/lawyers/family-law/new-york"
            ],
            "items": {
              "type": "string"
            }
          },
          "fetchDetails": {
            "title": "Fetch full profile details (richer records)",
            "type": "boolean",
            "description": "Open each attorney profile page to add badges, biography, practice areas with sub-specialties, multiple offices with weekly hours, education, experience, awards, professional associations, jurisdictions, languages, certifications, speaking engagements, social profiles, peer endorsements, and the Justia Lawyer Rating breakdown. Adds one HTTP request per attorney.",
            "default": true
          },
          "fetchVcard": {
            "title": "Fetch vCard (structured contact data)",
            "type": "boolean",
            "description": "In search mode this only applies when Fetch full profile details is on (otherwise it has no effect); pasted profile URLs always load the profile. Downloads the .vcf file each profile exposes to add a structured vCard block: name parts, fax, organization, structured address, URLs. Adds one small HTTP request per attorney. Off by default (the HTML page already covers most fields).",
            "default": false
          },
          "minRating": {
            "title": "Min Justia rating",
            "minimum": 0,
            "maximum": 10,
            "type": "number",
            "description": "Only keep attorneys with at least this Justia Lawyer Rating (0 to 10 scale)."
          },
          "freeConsultationOnly": {
            "title": "Free consultation only",
            "type": "boolean",
            "description": "Only keep attorneys who advertise a free consultation.",
            "default": false
          },
          "topRatedOnly": {
            "title": "Top-rated only",
            "type": "boolean",
            "description": "Only keep attorneys with the maximum Justia Lawyer Rating (10.0).",
            "default": false
          },
          "maxPages": {
            "title": "Max pages per list",
            "minimum": 0,
            "type": "integer",
            "description": "How many result pages to read per directory URL. Does NOT cap the run. Leave empty (or 0) for unlimited pages. The run is bounded by Max results, which is the cap.",
            "default": 0
          },
          "maxItems": {
            "title": "Max results",
            "minimum": 0,
            "maximum": 1000000,
            "type": "integer",
            "description": "THE cap for the run: stop after this many attorney records (default 20). Set to 0 for unlimited. Values above 1,000,000 are not accepted.",
            "default": 20
          },
          "proxy": {
            "title": "Proxy",
            "type": "object",
            "description": "Network connection. Leave this at the default (Residential, US) unless you have a specific reason to change it. Residential requires a paid Apify plan.",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": [
                "RESIDENTIAL"
              ],
              "apifyProxyCountry": "US"
            }
          },
          "resumeFromRunId": {
            "title": "Resume from run ID",
            "type": "string",
            "description": "Optional: paste a previous run ID (or dataset ID) from this actor. Attorneys already collected there are skipped, so this run only returns new ones. Leave empty for a normal run."
          },
          "incrementalMode": {
            "title": "Incremental changes for scheduled runs",
            "type": "boolean",
            "description": "Turn this on for daily or recurring monitoring of the same search or URLs. The first run returns every attorney as NEW. Later runs normally return only NEW, UPDATED, and REAPPEARED attorneys. Turn on \"Emit unchanged\" or \"Emit expired\" only when you also want those returned (and billed). State is kept separately per search/URL and filter/detail setup; use State key to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from run ID above. Change detection compares every returned field except scrapedAt, sourceUrl, metadata and vcard (run bookkeeping); the order of plain lists such as phone numbers is ignored. Add more with Ignore fields when detecting changes.",
            "default": false
          },
          "stateKey": {
            "title": "State key (optional, incremental mode only)",
            "type": "string",
            "description": "Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Leave empty to let the actor derive a key automatically from the search/URL and filter/detail settings, so different searches never mix state with each other."
          },
          "emitUnchanged": {
            "title": "Emit unchanged attorneys (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return attorneys that have not changed since the last run, marked UNCHANGED. This returns, and bills, extra rows you already have, so leave it off unless you specifically want the full snapshot every run.",
            "default": false
          },
          "emitExpired": {
            "title": "Emit expired attorneys (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return attorneys that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search, not when Max results/Max pages capped it, or when Resume from run ID was used. This returns, and bills, extra synthetic rows, so leave it off unless you need expiry tracking.",
            "default": false
          },
          "ignoreFieldsForChanges": {
            "title": "Ignore fields when detecting changes (incremental mode only)",
            "type": "array",
            "description": "Optional. Field names to leave out when deciding whether an attorney changed, for example `biography` or `awards`. Use a dotted path such as `peerReviews.date` for a field inside a list or object. Ignored fields are still returned in the output; they just never turn an attorney into UPDATED or appear in changedFields. Already ignored by default: scrapedAt, sourceUrl, metadata and vcard, and the order of plain lists such as phone numbers or languages.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "mcpConnectors": {
            "title": "Pipe results into your apps (optional)",
            "type": "array",
            "description": "Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify, Settings, Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON; the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com)."
          },
          "notionParentPageUrl": {
            "title": "Notion parent page (Notion connector only)",
            "type": "string",
            "description": "URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors."
          },
          "maxNotifyListings": {
            "title": "Max items to export per connector",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap on items written to each connector per run. Does not affect the dataset.",
            "default": 50
          }
        }
      },
      "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}