# JusBrasil Court Scraper | 1$/1k Cheap (`trev0n/jusbrasil-court-scraper`) Actor

Extract Brazilian court decisions and jurisprudence (STJ, STF, state TJ, federal TRF, labour TST) from JusBrasil.com.br — full ementa and acórdão text, court, judging body, rapporteur, dates and process data. Ideal for legal research, law firms, legal-tech and NLP.

- **URL**: https://apify.com/trev0n/jusbrasil-court-scraper.md
- **Developed by:** [Paweł](https://apify.com/trev0n) (community)
- **Categories:** AI, Developer tools, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 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

## ⚖️ JusBrasil Court Scraper — Brazilian Jurisprudence & Court Decisions

🎯 **Pull full Brazilian court decisions and case law from JusBrasil in clean, structured JSON — by keyword, process number, or court.**

This scraper searches JusBrasil's jurisprudence database and collects complete decisions from the STF, STJ, TST, state Courts of Justice (TJ) and Federal Regional Courts (TRF). For every ruling you get the full ementa (summary), the acórdão (decision text), an AI-generated plain-language summary, the judging body, the rapporteur, judgment and publication dates, and links to the full-text document.

### 🚀 What Does It Do?

This scraper automatically searches Brazilian jurisprudence and collects **structured, ready-to-use data** for every court decision it finds. No manual browsing, no copy-paste — just set your keywords and hit Start.

💡 **Two modes of operation:**

1. **🔍 Discovery Mode** — Enter a search term (e.g. _"responsabilidade civil"_) or a CNJ process number, optionally pick a court, and the scraper gathers matching decisions across as many result pages as you need.
2. **📋 Direct URL Mode** — Paste specific JusBrasil search or decision URLs and the scraper extracts exactly those.

### 👥 Who Is This For?

| 🏢 Use Case                          | 💬 How It Helps                                                                                     |
| ------------------------------------ | --------------------------------------------------------------------------------------------------- |
| ⚖️ **Lawyers & Law Firms**           | Build precedent files in minutes — find the rulings that support your case across every major court |
| 📚 **Legal Researchers & Academics** | Collect large, structured samples of case law for studies, papers and citation analysis             |
| 🤖 **Legal-Tech & NLP Teams**        | Feed clean ementa and acórdão text into models for classification, summarization and search         |
| 📰 **Journalists & Analysts**        | Track how courts rule on a topic over time and surface patterns across tribunals                    |
| 🏛️ **Compliance & Risk Teams**       | Monitor judicial trends on liability, consumer law and regulatory matters                           |

### ✨ Features

- 🌐 **Every Major Court** — STF, STJ, TST, state TJ courts and federal TRF regions, all from one search
- 📜 **Full Decision Text** — Complete ementa (summary) and acórdão (ruling), not just snippets
- 🧠 **AI Summary Included** — A plain-language summary of each decision, ready to skim
- 🏷️ **Rich Metadata** — Judging body, rapporteur, instance, judgment & publication dates, precedent flags
- 🔢 **CNJ Process Lookup** — Search by process number, not just keywords
- 🎛️ **Smart Filters** — Narrow results to a single court, set a page cap, choose fast or full-detail mode
- ⚡ **Fast & Scalable** — Collect dozens to hundreds of decisions per run; first results in under a minute
- 🧹 **Clean, Deduplicated Output** — No duplicate decisions, consistent camelCase fields, ISO dates
- 📤 **Export Anywhere** — Download results as JSON, CSV, Excel, or push to Google Sheets, Zapier, Make, or your CRM

### 🎛️ Filters & Options

| Option                  | What It Does                                                                               |
| ----------------------- | ------------------------------------------------------------------------------------------ |
| 🔎 **Search Query**     | The keywords to search jurisprudence for (e.g. _dano moral_, _improbidade administrativa_) |
| 🏛️ **Court / Tribunal** | Restrict results to one court (STJ, STF, TST, TJSP, TJRJ, TRF1–5 and more)                 |
| 🔢 **Process Number**   | Look up a specific case by its CNJ process number                                          |
| 📜 **Fetch Full Text**  | On: full ementa, acórdão, references and AI summary. Off: faster, lighter listing data     |
| 📄 **Max Search Pages** | How many result pages to page through per search                                           |
| 🔢 **Max Results**      | Control how many decisions to extract per run                                              |
| 🔗 **Direct URLs**      | Optionally provide specific JusBrasil search or decision URLs to scrape                    |

### 📦 What You Get (Output Fields)

Every decision includes:

#### Case Identification

| Field           | Example                                                              |
| --------------- | -------------------------------------------------------------------- |
| title           | `Superior Tribunal de Justiça STJ - RECURSO ESPECIAL: REsp XXXXX RS` |
| court           | `STJ`                                                                |
| courtName       | `Superior Tribunal de Justiça`                                       |
| instance        | `Superior Court`                                                     |
| state           | `MG`                                                                 |
| proceduralClass | `Apelação Cível`                                                     |
| processNumber   | `0012345-67.2019.8.13.0024`                                          |
| type            | `ACORDAO`                                                            |
| docId           | `1554600400`                                                         |

#### Decision Content

| Field           | Example                                                                                       |
| --------------- | --------------------------------------------------------------------------------------------- |
| subject         | `ADMINISTRATIVO. RESPONSABILIDADE CIVIL DO ESTADO POR OMISSÃO...`                             |
| decisions       | `["Vistos e relatados estes autos, acordam os Ministros da Turma..."]`                        |
| decisionSummary | `No recurso especial, a parte buscou a condenação da Fundação ao pagamento de indenização...` |
| keywords        | `Constituição Federal de 1988, Art. 37; Lei nº 8.078/1990`                                    |

#### People & Parties

| Field       | Example                              |
| ----------- | ------------------------------------ |
| judge       | `Ministro RICARDO VILLAS BÔAS CUEVA` |
| judgingBody | `T2 - SEGUNDA TURMA`                 |
| parties     | `["Recorrente: Fazenda Pública"]`    |
| lawyers     | `["OAB/SP 123456"]`                  |

#### Dates, Flags & Valuation

| Field                   | Example          |
| ----------------------- | ---------------- |
| judgmentDate            | `2022-05-24`     |
| publicationDate         | `DJe 24/06/2022` |
| readingTimeMinutes      | `75`             |
| isMeritDecision         | `false`          |
| isAdmissibilityDecision | `false`          |
| isMandatoryPrecedent    | `false`          |
| isHistoryPrecedent      | `false`          |
| claimValue              | `R$ 50.000,00`   |

#### References & Links

| Field              | Example                                                      |
| ------------------ | ------------------------------------------------------------ |
| processUrl         | `https://www.jusbrasil.com.br/jurisprudencia/stj/1554600400` |
| inteiroTeorFile    | `STJ_RESP_1708325_c4d00.pdf`                                 |
| lawReferences      | `["Art. 37 da Constituição Federal"]`                        |
| decisionReferences | `["REsp 1.234.567/SP"]`                                      |
| relatedProcesses   | `[]`                                                         |
| score              | `0`                                                          |
| slug               | `recurso-especial-resp-1708325-rs-2015-0273254-9`            |
| source             | `jusbrasil`                                                  |
| scrapedAt          | `2026-06-29T14:56:20.895Z`                                   |

### 📊 Example Output

```json
{
    "title": "Superior Tribunal de Justiça STJ - RECURSO ESPECIAL: REsp XXXXX RS",
    "court": "STJ",
    "courtName": "Superior Tribunal de Justiça",
    "instance": "Superior Court",
    "state": null,
    "proceduralClass": "REsp XXXXX RS",
    "processNumber": null,
    "type": "ACORDAO",
    "docId": "1554600400",
    "judgingBody": "T2 - SEGUNDA TURMA",
    "judge": "Ministro RICARDO VILLAS BÔAS CUEVA",
    "subject": "ADMINISTRATIVO. RECURSO ESPECIAL. RESPONSABILIDADE CIVIL DO ESTADO POR OMISSÃO. MORTE EM DECORRÊNCIA DE DISPARO DE ARMA DE FOGO...",
    "decisions": [
        "Vistos e relatados estes autos em que são partes as acima indicadas, acordam os Ministros da Turma, por unanimidade, dar provimento ao recurso..."
    ],
    "decisionSummary": "No recurso especial, a parte buscou a condenação ao pagamento de indenização por danos morais e materiais decorrentes...",
    "keywords": "Constituição Federal de 1988, Art. 37; Lei nº 8.078/1990",
    "parties": [],
    "lawyers": [],
    "claimValue": null,
    "isMeritDecision": false,
    "isAdmissibilityDecision": false,
    "isMandatoryPrecedent": false,
    "isHistoryPrecedent": false,
    "judgmentDate": "2022-05-24",
    "publicationDate": "DJe 24/06/2022",
    "readingTimeMinutes": 75,
    "inteiroTeorFile": "STJ_RESP_1708325_c4d00.pdf",
    "lawReferences": [],
    "decisionReferences": [],
    "relatedProcesses": [],
    "processUrl": "https://www.jusbrasil.com.br/jurisprudencia/stj/1554600400",
    "slug": "recurso-especial-resp-1708325-rs-2015-0273254-9",
    "score": 0,
    "sourceType": "jurisprudencia",
    "source": "jusbrasil",
    "scrapedAt": "2026-06-29T14:56:20.895Z"
}
````

### 📋 Dataset Views

The Apify Console gives you **4 ready-made table views** to quickly browse your results:

| View                    | What It Shows                                                                 |
| ----------------------- | ----------------------------------------------------------------------------- |
| 📊 **Overview**         | Title, court, judging body, rapporteur and dates — the at-a-glance list       |
| ⚖️ **Legal & Parties**  | Court, process, instance, rapporteur, parties, lawyers, claim value and dates |
| 📜 **Decision Content** | Ementa, AI summary, ruling text and the full-text file                        |
| 📋 **Full Details**     | Every single field — the complete dataset                                     |

### ❓ FAQ

**🤔 Which courts are covered?**
The STF, STJ and TST (superior courts), every state Court of Justice (TJSP, TJRJ, TJMG, TJRS, TJPR and the rest), and all five Federal Regional Courts (TRF1–TRF5) — anything indexed in JusBrasil's jurisprudence collection.

**🤔 Can I search by process number?**
Yes — enter a CNJ process number instead of keywords and the scraper looks it up. Note that for anonymous access some process numbers are masked by the source.

**🤔 Why are some fields (lawyers, parties, full process number) empty?**
JusBrasil shows full ementa and acórdão text publicly, but masks certain personal details (party names, lawyers, complete process numbers) unless you are logged in. The scraper returns everything that is publicly available.

**🤔 Do I get the full decision text or just a summary?**
Both. You get the full ementa and acórdão text, plus a plain-language AI summary. Turn off "Fetch Full Text" for a faster run that returns just the listing-level fields.

**🤔 Can I export the data?**
Yes — JSON, CSV, Excel, XML, HTML, RSS. You can also push data directly to Google Sheets, Zapier, Make, or any webhook/API endpoint.

**🤔 How often should I run this?**
For fresh case law, run daily or weekly. You can schedule automatic runs on Apify with just a few clicks.

**🤔 Does it work with proxies?**
Yes — Brazilian residential proxies are recommended and used by default for the best results, via Apify's built-in proxy service.

### 🛠️ Need Custom Filters or Features?

**I'm happy to customize this scraper for your specific needs!** 🤝

Whether you need:

- 🎯 Additional filters (by date range, judging body, decision type, or specific rapporteur)
- 📊 Extra data fields or custom output formats
- 🔄 Integration with your CRM, Google Sheets, or database
- ⏰ Scheduled scraping with automatic deduplication and change tracking
- 🌐 Scraping from other Brazilian legal sources alongside JusBrasil

👉 **Don't hesitate to reach out via private message** — I respond quickly and I'm always open to building exactly what you need. No request is too small or too specific!

### ⚖️ Legal & Ethical Use

This scraper collects **only publicly available information** from JusBrasil. It does not access private data, bypass authentication, or retrieve login-gated content. Please use the data responsibly and in compliance with applicable laws and platform terms of service.

# Actor input Schema

## `searchQuery` (type: `string`):

Keywords to search Brazilian jurisprudence for, e.g. "responsabilidade civil", "dano moral", "improbidade administrativa". The actor builds the JusBrasil search URL from this. Ignored if you provide Start URLs below.

## `court` (type: `string`):

Restrict the search to a single court. Leave as "All courts" to search every tribunal at once.

## `fullText` (type: `boolean`):

When on (default), each decision is opened to collect the full ementa, acórdão ruling text, judging body, rapporteur, dates, references and an AI summary. Turn off for a faster, lighter run that returns just the search-result fields (title, court, ementa snippet, dates).

## `processNumber` (type: `string`):

Look up a specific case by its CNJ process number, e.g. "0001234-56.2020.8.26.0100". When provided, this is used as the search query. Availability of full process data depends on the court.

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

Direct JusBrasil URLs to scrape — either jurisprudence search pages (…/jurisprudencia/busca?q=…) or individual decision pages (…/jurisprudencia/stj/123456789/…). When provided, these override the search query + court above.

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

Stop after collecting this many decision records across all search pages.

## `maxPagesPerSearch` (type: `integer`):

Safety cap on how many result pages to paginate through per search before stopping.

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

How many searches to process in parallel (each runs its own stealth browser). Pagination and detail fetching within a search stay sequential. Keep modest.

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

How many times to retry clearing Cloudflare / loading a page before giving up.

## `debugDumpHtml` (type: `boolean`):

Save the rendered HTML of each page to the key-value store (for troubleshooting parser issues). Leave off for normal runs.

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

JusBrasil blocks datacenter IPs at the Cloudflare layer — RESIDENTIAL proxies are required. Brazilian IPs clear the challenge most reliably.

## Actor input object example

```json
{
  "searchQuery": "responsabilidade civil",
  "court": "",
  "fullText": true,
  "processNumber": "0001234-56.2020.8.26.0100",
  "maxItems": 20,
  "maxPagesPerSearch": 20,
  "maxConcurrency": 2,
  "maxRequestRetries": 4,
  "debugDumpHtml": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "BR"
  }
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

# 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 = {
    "searchQuery": "responsabilidade civil",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "BR"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("trev0n/jusbrasil-court-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 = {
    "searchQuery": "responsabilidade civil",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "BR",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("trev0n/jusbrasil-court-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 '{
  "searchQuery": "responsabilidade civil",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "BR"
  }
}' |
apify call trev0n/jusbrasil-court-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "JusBrasil Court Scraper | 1$/1k Cheap",
        "description": "Extract Brazilian court decisions and jurisprudence (STJ, STF, state TJ, federal TRF, labour TST) from JusBrasil.com.br — full ementa and acórdão text, court, judging body, rapporteur, dates and process data. Ideal for legal research, law firms, legal-tech and NLP.",
        "version": "1.0",
        "x-build-id": "jHy1pyIIRMr1Vj70i"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/trev0n~jusbrasil-court-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-trev0n-jusbrasil-court-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/trev0n~jusbrasil-court-scraper/runs": {
            "post": {
                "operationId": "runs-sync-trev0n-jusbrasil-court-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/trev0n~jusbrasil-court-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-trev0n-jusbrasil-court-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": {
                    "searchQuery": {
                        "title": "Search query",
                        "type": "string",
                        "description": "Keywords to search Brazilian jurisprudence for, e.g. \"responsabilidade civil\", \"dano moral\", \"improbidade administrativa\". The actor builds the JusBrasil search URL from this. Ignored if you provide Start URLs below."
                    },
                    "court": {
                        "title": "Court / tribunal filter",
                        "enum": [
                            "",
                            "STJ",
                            "STF",
                            "TST",
                            "TJSP",
                            "TJRJ",
                            "TJMG",
                            "TJRS",
                            "TJPR",
                            "TJSC",
                            "TJBA",
                            "TJDF",
                            "TJGO",
                            "TJPE",
                            "TJCE",
                            "TRF1",
                            "TRF2",
                            "TRF3",
                            "TRF4",
                            "TRF5"
                        ],
                        "type": "string",
                        "description": "Restrict the search to a single court. Leave as \"All courts\" to search every tribunal at once.",
                        "default": ""
                    },
                    "fullText": {
                        "title": "Fetch full decision text",
                        "type": "boolean",
                        "description": "When on (default), each decision is opened to collect the full ementa, acórdão ruling text, judging body, rapporteur, dates, references and an AI summary. Turn off for a faster, lighter run that returns just the search-result fields (title, court, ementa snippet, dates).",
                        "default": true
                    },
                    "processNumber": {
                        "title": "Process number (CNJ)",
                        "type": "string",
                        "description": "Look up a specific case by its CNJ process number, e.g. \"0001234-56.2020.8.26.0100\". When provided, this is used as the search query. Availability of full process data depends on the court."
                    },
                    "startUrls": {
                        "title": "Start URLs (optional)",
                        "type": "array",
                        "description": "Direct JusBrasil URLs to scrape — either jurisprudence search pages (…/jurisprudencia/busca?q=…) or individual decision pages (…/jurisprudencia/stj/123456789/…). When provided, these override the search query + court above.",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "maxItems": {
                        "title": "Maximum results",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Stop after collecting this many decision records across all search pages.",
                        "default": 20
                    },
                    "maxPagesPerSearch": {
                        "title": "Max search pages",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Safety cap on how many result pages to paginate through per search before stopping.",
                        "default": 20
                    },
                    "maxConcurrency": {
                        "title": "Max concurrency",
                        "minimum": 1,
                        "maximum": 8,
                        "type": "integer",
                        "description": "How many searches to process in parallel (each runs its own stealth browser). Pagination and detail fetching within a search stay sequential. Keep modest.",
                        "default": 2
                    },
                    "maxRequestRetries": {
                        "title": "Max request retries",
                        "minimum": 1,
                        "maximum": 10,
                        "type": "integer",
                        "description": "How many times to retry clearing Cloudflare / loading a page before giving up.",
                        "default": 4
                    },
                    "debugDumpHtml": {
                        "title": "Debug: dump rendered HTML",
                        "type": "boolean",
                        "description": "Save the rendered HTML of each page to the key-value store (for troubleshooting parser issues). Leave off for normal runs.",
                        "default": false
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "JusBrasil blocks datacenter IPs at the Cloudflare layer — RESIDENTIAL proxies are required. Brazilian IPs clear the challenge most reliably.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ],
                            "apifyProxyCountry": "BR"
                        }
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
