# German Lawyers Scraper (BRAK / BRAV Official Register) (`iiphantom/brak-german-lawyers-scraper`) Actor

Scrape the official German lawyer register (BRAK / BRAV public search at bravsearch.bea-brak.de) into structured JSON. Public search only — no login, no Anwalt.de. Pay only for unique lawyers delivered. Honest ~100-hit soft cap; narrow filters required.

- **URL**: https://apify.com/iiphantom/brak-german-lawyers-scraper.md
- **Developed by:** [Elisha](https://apify.com/iiphantom) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.00 / 1,000 lawyer records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## German Lawyers Scraper (BRAK / BRAV Official Register)

**Turn the official German lawyer register (BRAK / BRAV) into clean, structured JSON. Public search only — no login, no Anwalt.de, pay only for the lawyers you get.**

Germany’s Bundesrechtsanwaltskammer publishes a nationwide official directory of admitted lawyers. This Actor reads the **public** BRAV search at `bravsearch.bea-brak.de` the same way a human researcher would: narrow filters (city, chamber, Fachanwalt, name), list cards, optional detail fields (contacts, beA SAFE-ID, specializations). You get one consistent dataset row per lawyer.

> **Important soft cap:** the public UI effectively exposes about **~100 browsable hits per search query**. Broad queries (e.g. “all Berlin”) will not dump the full register. Use **Fachanwalt + city/PLZ/chamber** and/or **name shards** (`lastName`) — or the multi-`queries` input — to cover a niche honestly.

***

### Who it's for

- **Legal-tech and referral marketplaces.** Chamber-verified lawyer rows (name, Kanzlei, Fachanwalt, city, public contacts) from the official register.
- **Law-firm marketing / SEO agencies.** Build city × specialty lists for content targeting and compliant outreach planning (you remain responsible under GDPR / UWG).
- **Insurance, claims, and panel-counsel builders.** Filter by Fachanwalt + Kammer for panel construction.
- **Compliance / KYB enrichment.** “Is this person admitted?” style checks against the canonical public source.

***

### What you get

- ✅ **Official BRAK / BRAV source only** — not a commercial directory scrape. **Anwalt.de is out of scope.**
- ✅ **Structured lawyer rows:** name, title, address, chamber (Kammer), admission date (when shown), Fachanwalt specializations, Pflichtverteidiger flag, public phone / mobile / fax / email / website, beA SAFE-ID when published on the detail view.
- ✅ **Narrow filters that match the real UI:** city, PLZ prefix, chamber, Fachanwalt, name, office name, Pflichtverteidiger-only.
- ✅ **Optional multi-shard `queries`** so you can cover a large niche without pretending one query returns everything.
- ✅ **Optional detail fetch** per card (Kammer, contacts, beA, specializations).
- ✅ **Empty searches, failures and duplicates are free.** You pay only for unique lawyers delivered.
- ✅ **HTTP / PrimeFaces AJAX client** — no browser farm required for MVP; polite delays by default.
- ✅ **Honest about the ~100-hit soft cap** — warnings in the run log when the register reports more hits than can be browsed.
- ✅ Export as JSON, CSV, Excel, or via API, webhooks, Make, n8n or Zapier.

***

### How to use

1. Click **Try for free** (prefill: `city=Berlin`, `fachanwalt=Arbeitsrecht`, `maxResults=25`, `includeDetails=true`).
2. Set at least one narrowing filter, for example:
   - **City** `Berlin` + **Fachanwalt** `Arbeitsrecht`
   - **Chamber** Berlin (`B`) + **Pflichtverteidiger only**
   - **City** + **lastName** letter shards (`A`, `B`, `C`, …) via `queries`
3. Leave **Include details** on if you need email / phone / beA / specializations.
4. Set **Max results** ≤ 100 (default 100).
5. Click **Start** and download your dataset.

**Why did I only get 100 rows when the register says thousands?** That is a limitation of the public search UI (~100 browsable hits per query). Narrow the query or split into shards — see FAQ.

#### Input fields

| Field | What it does | Default |
| --- | --- | --- |
| `city` | Ort filter | empty |
| `postalCodePrefix` | PLZ prefix | empty |
| `chamber` | Rechtsanwaltskammer code (e.g. `B` = Berlin) | empty |
| `fachanwalt` | Fachanwalt specialization label | empty |
| `lastName` / `firstName` | Name filters / sharding | empty |
| `officeName` | Kanzlei name filter | empty |
| `pflichtverteidigerOnly` | Only lawyers marked Pflichtverteidiger | `false` |
| `includeDetails` | Fetch detail dialog fields | `true` |
| `maxResults` | Cap per run/query (**max 100**) | `100` |
| `queries` | Array of shard filter objects (optional) | `[]` |
| `requestDelayMs` / `maxConcurrency` | Politeness (keep concurrency at 1) | `1000` / `1` |
| `proxyConfiguration` | Optional Apify datacenter proxy | off |

At least one narrowing field (or a non-empty `queries` list) is required.

#### Sample input

```json
{
  "city": "Berlin",
  "chamber": "B",
  "fachanwalt": "Arbeitsrecht",
  "includeDetails": true,
  "maxResults": 100,
  "requestDelayMs": 1000
}
```

#### Sample multi-shard input

```json
{
  "includeDetails": true,
  "maxResults": 100,
  "queries": [
    { "city": "Berlin", "fachanwalt": "Arbeitsrecht", "lastName": "A" },
    { "city": "Berlin", "fachanwalt": "Arbeitsrecht", "lastName": "B" },
    { "city": "Berlin", "fachanwalt": "Arbeitsrecht", "lastName": "C" }
  ]
}
```

***

### Sample output

One dataset item per lawyer (illustrative shape):

```json
{
  "fullName": "Aalderks, Dirk Johann Dr. jur.",
  "title": "Rechtsanwalt",
  "street": "Beispielstraße 1",
  "postalCode": "10247",
  "city": "Berlin",
  "country": "DE",
  "chamber": "Rechtsanwaltskammer Berlin",
  "chamberCode": "B",
  "admissionDate": "2001-05-14",
  "specializations": ["Arbeitsrecht"],
  "pflichtverteidiger": false,
  "phone": "+49 30 123456",
  "email": "kanzlei@example.de",
  "website": "https://www.example-kanzlei.de",
  "beaSafeId": "DE.JUSTIZ.…",
  "source": "BRAK",
  "sourceUrl": "https://bravsearch.bea-brak.de/bravsearch/",
  "detailFetched": true,
  "lawyerKey": "a1b2c3d4e5f60718293a4b5c6d7e8f9012345678",
  "scrapedAt": "2026-10-05T18:58:00Z"
}
```

Dataset views: **Overview** (name, title, city, chamber, specializations, email, phone, website) and **Full**.

***

### Pricing: pay per event

**$4.00 per 1,000 lawyers** ($0.004 per lawyer delivered to your dataset).

| You run… | Lawyers charged | You pay |
| --- | --- | --- |
| Berlin × Arbeitsrecht demo, 25 details | 25 | ~$0.10 |
| One niche shard, 100 lawyers | 100 | ~$0.40 |
| 10 shards × 100 (deduped ≈ 900) | 900 | ~$3.60 |
| 1,000 unique lawyers | 1,000 | **$4.00** |

**Free:** empty searches, failed or blocked queries, duplicates within a run. No extra per-run fee from us when Console allows a zero/omitted start charge (standard Apify platform rules still apply). Set a **maximum cost per run** in Apify; the Actor stops cleanly when it is reached.

***

### FAQ

**Do I need a BRAK account or login?** No. The Actor uses only the public BRAV search (Einsichtnahme without registration).

**Does it scrape Anwalt.de?** No. Anwalt.de is explicitly out of scope. Official BRAK / BRAV register only.

**Why only ~100 results?** The public PrimeFaces results grid effectively caps browsable hits around 100 per query, even when “Anzahl gefundener Einträge” is higher. Narrow filters or use `queries` / `lastName` shards. The run summary warns when the register reported more hits than were returned.

**Can I download every lawyer in Germany in one run?** Not via a single broad query. Plan sharded runs (specialty × region × name letters). That is by design of the public UI, not an artificial Actor limit we invented to upsell.

**Are emails and phones included?** Only when they appear on the **public** detail view, and only if `includeDetails=true`. You are the **controller** of any further use — see Responsible use.

**Do you bypass CAPTCHAs or spoof browsers?** No. Public pages only, honest User-Agent, polite delays. If the register starts challenging datacenter traffic, runs fail cleanly and those failures are free.

**Is this affiliated with BRAK?** No. Independent tool — see disclaimer below.

***

### Responsible use / UWG / GDPR

- **Buyers are controllers.** Output includes **professional personal data** (names, sometimes emails, phones, beA SAFE-IDs) from a public register. If you store or further process it, **you** must have a lawful basis under the GDPR (and respect Swiss FADP where relevant). This Actor does not supply that basis.
- **No spam / DE UWG.** Do **not** use the dataset for unlawful unsolicited advertising or cold email/phone campaigns to lawyers. German UWG rules on cold outreach are strict; “I bought a lead list” is not a defence.
- **Public register only.** The Actor requests only publicly available BRAV search and detail fragments. It does **not** log in, solve CAPTCHAs, fingerprint-spoof, or access non-public beA messaging content.
- **Polite use.** Default ~1 s delay between requests, concurrency 1, backoff on errors, automatic stop on blocks. Do not schedule aggressive sub-hourly hammering of the same filters.
- **No non-public data.** If a field is not shown to an anonymous public user, it will not appear in the dataset.

***

### Disclaimer

This Actor is built and maintained by Frontiersman (independent community publisher). It is **not affiliated with, endorsed by, or sponsored by** the Bundesrechtsanwaltskammer (BRAK), BRAV, beA, or any Rechtsanwaltskammer. “BRAK”, “BRAV”, “Anwaltsverzeichnis” and related marks are used only to describe compatibility with the public register. All trademarks belong to their owners.

Rights holders with concerns can contact us via the Apify Issues tab; we respond within 12 hours on business days.

***

### Roadmap

*Planned, subject to demand. Independent community Actor — not a BRAK product.*

- 🔜 Helper presets for common Fachanwalt × city packs.
- 🔜 Better guided sharding wizard when register-reported hits ≫ 100.
- 🔜 Optional list-only cheaper event (if demand appears).
- ❌ Anwalt.de support is **not** on the roadmap while anti-bot bypass would be required.

Missing a field? Open an issue. We read every one.

***

*Actor README · 2026-10-05 · PPE lock $4.00 / 1k lawyers · Softgarden Actor #1 unchanged · local build only (no Store publish).*

# Actor input Schema

## `city` (type: `string`):

Maps to search Ort / txtOrt. Example: Berlin, München. At least one narrowing filter is required.

## `postalCodePrefix` (type: `string`):

Maps to txtPostal. Example: 10, 803. Prefer with Fachanwalt/chamber for sharding.

## `chamber` (type: `string`):

Kammer code for ddRAKammer (e.g. B = Berlin). Frozen from live bravsearch UI 2026-10-05.

## `fachanwalt` (type: `string`):

Fachanwalt label (mapped to bravsearch option). Strongly recommended to stay under the ~100-hit soft cap.

## `lastName` (type: `string`):

Name filter / sharding tool (e.g. A, Be, Müller). Primary tool for large cities.

## `firstName` (type: `string`):

Optional first-name filter.

## `officeName` (type: `string`):

Kanzlei name filter when present in the UI.

## `pflichtverteidigerOnly` (type: `boolean`):

Restrict to lawyers marked interested in court-appointed defence counsel.

## `includeDetails` (type: `boolean`):

Extra AJAX per card for Kammer, contacts, beA SAFE-ID, admission dates. false = list-card fields only (same PPE event).

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

Hard cap per run/query. Ceiling = 100 (bravsearch soft browsable window). Values >100 are clamped with a warning.

## `queries` (type: `array`):

Optional array of filter objects (city/chamber/fachanwalt/lastName/…). Each shard runs as its own search (own ≤100 window). Deduped by lawyerKey before charge.

## `language` (type: `string`):

bravsearch UI locale preference for labels in logs; register content is German.

## `requestDelayMs` (type: `integer`):

Min delay between page/detail AJAX calls (±30% jitter). Floor 500 ms.

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

Keep 1 for MVP (single session / ViewState). Raising risks session races.

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

Optional Apify datacenter proxy. Never used to evade a block; no residential-as-bypass.

## Actor input object example

```json
{
  "city": "Berlin",
  "postalCodePrefix": "",
  "chamber": "",
  "fachanwalt": "Arbeitsrecht",
  "lastName": "",
  "firstName": "",
  "officeName": "",
  "pflichtverteidigerOnly": false,
  "includeDetails": true,
  "maxResults": 25,
  "queries": [],
  "language": "de",
  "requestDelayMs": 1000,
  "maxConcurrency": 1,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `lawyers` (type: `string`):

Structured lawyer rows in the default dataset.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

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

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "city": "Berlin",
    "fachanwalt": "Arbeitsrecht",
    "includeDetails": true,
    "maxResults": 25
};

// Run the Actor and wait for it to finish
const run = await client.actor("iiphantom/brak-german-lawyers-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 = {
    "city": "Berlin",
    "fachanwalt": "Arbeitsrecht",
    "includeDetails": True,
    "maxResults": 25,
}

# Run the Actor and wait for it to finish
run = client.actor("iiphantom/brak-german-lawyers-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "city": "Berlin",
  "fachanwalt": "Arbeitsrecht",
  "includeDetails": true,
  "maxResults": 25
}' |
apify call iiphantom/brak-german-lawyers-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,iiphantom/brak-german-lawyers-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

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