cd /news/ai-tools/how-to-download-german-federal-court… · home › topics › ai-tools › article
[ARTICLE · art-165327] src=dev.to ↗ pub= topic=ai-tools verified=true sentiment=↑ positive

How to download German federal court decisions (BGH, BVerfG, BAG) as JSON and Markdown for legal RAG

A developer built an Apify actor that converts German federal court decisions from rechtsprechung-im-internet.de into structured JSON and Markdown for legal RAG pipelines. The tool parses the portal's 23.5 MB XML index of 84,835 decisions and per-decision ZIP/XML files into fields such as Leitsatz, Tenor, Tatbestand, Gründe, Normen, Aktenzeichen and ECLI, with filters for court, date range, document type and keywords. A test run on 6 November 2026 returned three decisions in 45 seconds, and the developer recommends chunking along section boundaries while carrying case metadata into every chunk for citation.

by read4 min views3 publishedNov 6, 2026

If you build anything with German law, such as a legal research tool, a RAG assistant for a law firm or a monitor for new rulings, the best free source is the federal government's open-data portal rechtsprechung-im-internet.de. It lists decisions of all federal courts: Bundesgerichtshof (BGH), Bundesverfassungsgericht (BVerfG), Bundesverwaltungsgericht, Bundesfinanzhof, Bundesarbeitsgericht (BAG), Bundessozialgericht and Bundespatentgericht.

The catch is the format. There is no search API. You get a table of contents as one XML file (about 23.5 MB, 84,835 decisions when I fetched it on 5 November 2026) and, for each decision, a ZIP file containing an XML document in the court's own schema.

This guide shows how to turn that into clean JSON you can filter, store and embed.

Disclosure: I built the tool used below, German Federal Court Decisions on Apify. The approach works without it too; the last section shows what it saves you.

Yes. Court decisions are official works under § 5 of the German Copyright Act (UrhG) and are not protected by copyright. The decisions on the portal are already anonymised by the courts. That makes them one of the few large, clean, legally unproblematic text corpora for German-language legal AI.

Each decision XML has structured sections. The ones that matter most:

Field German term What it is
leitsatz Leitsatz The headnote: the legal rule the court establishes. The most valuable text for retrieval.
tenor Tenor The operative part: what was decided.
tatbestand Tatbestand The facts of the case.
entscheidungsgruende /gruende Entscheidungsgründe / Gründe The reasoning. Usually the longest part.
normen Normen The statutes the decision relies on (e.g. "§ 280 BGB").
fileNumber Aktenzeichen The case number, e.g. III ZR 3/26 .
ecli ECLI The European Case Law Identifier.

Not every decision has every section. Short procedural decisions (Beschlüsse) often have only a Tenor and Gründe and no Leitsatz.

With the actor, one HTTP call returns the decisions as JSON:

curl -X POST "https://api.apify.com/v2/acts/fast_data_asap~german-federal-court-decisions/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "courts": ["BGH", "BAG", "BVerfG"],
    "lastDays": 14,
    "maxDecisions": 6,
    "includeFullText": true,
    "outputFormat": "markdown"
  }'

I ran exactly this on 6 November 2026. It took 45 seconds, most of it spent the 23 MB index, and returned three decisions published in that window:

Court Date Aktenzeichen Type Words
BGH, 7. Zivilsenat 2026-10-28 VII ZB 47/25 Beschluss 1,872
BGH, 1. Zivilsenat 2026-10-28 I ZR 91/25 Beschluss 357
BVerfG, 2. Senat 2026-10-23 2 BvR 1421/26 rejected urgent application 1,056

Two practical notes:

ecli. Useful filters: dateFrom / dateTo, documentType (Urteil or Beschluss), fileNumber (e.g. "ZR" for civil senates) and keywords, which search the title and headnote, or with keywordsInFullText: true the full text.

Legal text chunks best along its own structure. Don't cut a Leitsatz in half, and keep the case number and court on every chunk so the assistant can cite properly:

import json

def chunks_for(decision, max_words=350):
    meta = {
        "court": decision["court"],
        "date": decision["decisionDate"],
        "aktenzeichen": decision["fileNumber"],
        "ecli": decision.get("ecli"),
        "normen": decision.get("normen") or [],
    }
    sections = [
        ("Leitsatz", decision.get("leitsatz")),
        ("Tenor", decision.get("tenor")),
        ("Tatbestand", decision.get("tatbestand")),
        ("Gründe", decision.get("entscheidungsgruende") or decision.get("gruende")),
    ]
    for name, text in sections:
        if not text:
            continue
        words = text.split()
        for start in range(0, len(words), max_words):
            part = " ".join(words[start:start + max_words])
            yield {**meta, "section": name, "text": part}

decisions = json.load(open("decisions.json"))
chunks = [c for d in decisions for c in chunks_for(d)]
print(len(chunks), "chunks")

Two tips that make a measurable difference in retrieval:

normen as metadata. A daily schedule with lastDays: 7 and the courts you care about, plus deduplication on ecli in your vector store, keeps the corpus current. For topic alerts, add keywords (for example ["DSGVO"] or ["Kündigung"]) and send new hits to Slack or e-mail with n8n or Make.

Doing this by hand means down and parsing the 23.5 MB index, mapping court names and senates, fetching and unzipping one archive per decision, parsing the court XML schema, converting its formatting to Markdown, and handling the portal's occasional stalls. The actor does all of that, retries stalled downloads, and only charges for decisions it actually returns: $0.001 per decision. Failed downloads are free.

The README has the full field list and more examples: German Federal Court Decisions on Apify.

Data: rechtsprechung-im-internet.de (Federal Ministry of Justice), fetched 5–6 November 2026. This article is about data access, not legal advice.

── more in #ai-tools 4 stories · sorted by recency
── more on @apify 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/how-to-download-germ…] indexed:0 read:4min 2026-11-06 · —