Use Cases

coleta autorizada de pesquisa jurídica com tratamento de CAPTCHA

PACER, tribunais estaduais e o SEC EDGAR têm o mesmo reflexo: assim que percebem um volume incomum de consultas vindo do mesmo IP, devolvem um reCAPTCHA v2 ou um CAPTCHA de imagem no lugar dos resultados. A CaptchaAI resolve esse desafio via API — o script recebe o token, envia a busca e segue para a próxima página sem intervenção manual. Este guia mostra como manter a pesquisa jurídica automatizada em execução ao consultar jurisprudência, acompanhar processos e reunir dados regulatórios nos principais sistemas dos EUA.

Cenário comum: uma equipe de compliance com operação no Brasil acompanha o SEC EDGAR antes de uma rodada de investimento, ou um escritório com filial em Lisboa monitora depósitos de patentes para due diligence de uma fusão. Nos dois casos a coleta roda por dias contra fontes que não foram desenhadas para tráfego automatizado — e o CAPTCHA costuma ser só o primeiro obstáculo, não o único.


Como resolver o CAPTCHA ao consultar jurisprudência

O fluxo abaixo resolve o reCAPTCHA quando a busca tem sitekey disponível e cai para o CAPTCHA de imagem quando não tem. Ele pagina os resultados até esgotar os casos ou a página parar de devolver itens novos.

import requests
import time
import re
import base64
from bs4 import BeautifulSoup
import csv

CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"


def solve_recaptcha(sitekey, pageurl):
    resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
        "key": CAPTCHAAI_KEY, "method": "userrecaptcha",
        "googlekey": sitekey, "pageurl": pageurl, "json": 1,
    })
    task_id = resp.json()["request"]
    for _ in range(60):
        time.sleep(5)
        result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
            "key": CAPTCHAAI_KEY, "action": "get",
            "id": task_id, "json": 1,
        })
        data = result.json()
        if data["request"] != "CAPCHA_NOT_READY":
            return data["request"]
    raise TimeoutError("Timeout")


def solve_image_captcha(image_bytes):
    img_b64 = base64.b64encode(image_bytes).decode()
    resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
        "key": CAPTCHAAI_KEY, "method": "base64",
        "body": img_b64, "json": 1,
    })
    task_id = resp.json()["request"]
    for _ in range(20):
        time.sleep(3)
        result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
            "key": CAPTCHAAI_KEY, "action": "get",
            "id": task_id, "json": 1,
        })
        data = result.json()
        if data["request"] != "CAPCHA_NOT_READY":
            return data["request"]
    raise TimeoutError("Timeout")


class LegalResearchScraper:
    def __init__(self, proxy=None):
        self.session = requests.Session()
        if proxy:
            self.session.proxies = {"http": proxy, "https": proxy}
        self.session.headers.update({
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36",
        })

    def search_cases(self, search_url, query, sitekey=None, max_pages=5):
        """Search case law database."""
        all_cases = []

        for page in range(max_pages):
            url = f"{search_url}?q={query}&page={page + 1}"
            resp = self.session.get(url, timeout=30)

            if self._has_captcha(resp.text):
                if sitekey:
                    token = solve_recaptcha(sitekey, url)
                    resp = self.session.post(url, data={
                        "q": query,
                        "g-recaptcha-response": token,
                    })
                else:
                    resp = self._solve_image_and_retry(resp.text, url, query)

            cases = self._parse_cases(resp.text)
            if not cases:
                break

            all_cases.extend(cases)
            print(f"Page {page + 1}: {len(cases)} cases")
            time.sleep(5)

        return all_cases

    def get_case_details(self, case_url):
        """Fetch full case details."""
        resp = self.session.get(case_url, timeout=30)

        if self._has_captcha(resp.text):
            sitekey = self._extract_sitekey(resp.text)
            if sitekey:
                token = solve_recaptcha(sitekey, case_url)
                resp = self.session.post(case_url, data={
                    "g-recaptcha-response": token,
                })

        soup = BeautifulSoup(resp.text, "html.parser")
        return {
            "title": self._text(soup, "h1, .case-title"),
            "citation": self._text(soup, ".citation, .case-cite"),
            "court": self._text(soup, ".court, .jurisdiction"),
            "date": self._text(soup, ".decision-date, .date-decided"),
            "judge": self._text(soup, ".judge, .authored-by"),
            "summary": self._text(soup, ".summary, .headnote"),
            "url": case_url,
        }

    def monitor_docket(self, docket_url, case_number, sitekey=None):
        """Monitor a specific case docket for new filings."""
        resp = self.session.get(docket_url, timeout=30)

        data = {"case_number": case_number}
        if sitekey and self._has_captcha(resp.text):
            token = solve_recaptcha(sitekey, docket_url)
            data["g-recaptcha-response"] = token

        resp = self.session.post(docket_url, data=data)
        return self._parse_docket(resp.text)

    def export_results(self, cases, filename):
        """Export case results to CSV."""
        if not cases:
            return
        with open(filename, "w", newline="", encoding="utf-8") as f:
            writer = csv.DictWriter(f, fieldnames=cases[0].keys())
            writer.writeheader()
            writer.writerows(cases)

    def _has_captcha(self, html):
        return any(tag in html.lower() for tag in [
            'data-sitekey', 'g-recaptcha', 'captcha',
        ])

    def _extract_sitekey(self, html):
        match = re.search(r'data-sitekey="([^"]+)"', html)
        return match.group(1) if match else None

    def _solve_image_and_retry(self, html, url, query):
        match = re.search(r'src="(/captcha[^"]+)"', html)
        if match:
            img_url = url.split("?")[0].rstrip("/") + match.group(1)
            img = self.session.get(img_url)
            answer = solve_image_captcha(img.content)
            return self.session.post(url, data={
                "q": query,
                "captcha": answer,
            })
        return self.session.get(url)

    def _parse_cases(self, html):
        soup = BeautifulSoup(html, "html.parser")
        cases = []
        for item in soup.select(".case-result, .search-result, tr.result"):
            title_el = item.select_one("a, .case-name")
            if title_el:
                cases.append({
                    "title": title_el.get_text(strip=True),
                    "url": title_el.get("href", ""),
                    "citation": self._text(item, ".citation, .cite"),
                    "date": self._text(item, ".date"),
                    "court": self._text(item, ".court"),
                })
        return cases

    def _parse_docket(self, html):
        soup = BeautifulSoup(html, "html.parser")
        entries = []
        for row in soup.select(".docket-entry, tr.filing"):
            entries.append({
                "date": self._text(row, ".date, td:first-child"),
                "entry": self._text(row, ".description, td:nth-child(2)"),
                "filed_by": self._text(row, ".filer, td:nth-child(3)"),
            })
        return entries

    def _text(self, el, selector):
        found = el.select_one(selector)
        return found.get_text(strip=True) if found else ""


# Usage
scraper = LegalResearchScraper(
    proxy="http://user:pass@residential.proxy.com:5000"
)

# Search case law
cases = scraper.search_cases(
    search_url="https://caselaw.example.com/search",
    query="data privacy GDPR",
    max_pages=5,
)

# Get details for relevant cases
for case in cases[:10]:
    if case["url"]:
        details = scraper.get_case_details(case["url"])
        print(f"{details['citation']}: {details['title']}")
        time.sleep(3)

# Export results
scraper.export_results(cases, "gdpr_cases.csv")

Monitoramento automatizado de novos processos e normas regulatórias

Para acompanhar várias fontes de uma vez — um número de processo específico, um feed de normas, uma lista de patentes — encapsule o buscador acima em um monitor que compara cada nova consulta com o que já foi visto e retorna apenas as novidades.

class RegulatoryMonitor:
    def __init__(self, proxy=None):
        self.scraper = LegalResearchScraper(proxy=proxy)
        self.seen_entries = set()

    def check_new_filings(self, feeds):
        """Check regulatory portals for new filings."""
        new_filings = []

        for feed in feeds:
            try:
                cases = self.scraper.search_cases(
                    feed["url"], feed["query"],
                    sitekey=feed.get("sitekey"),
                    max_pages=2,
                )

                for case in cases:
                    key = case.get("citation") or case.get("title")
                    if key and key not in self.seen_entries:
                        self.seen_entries.add(key)
                        case["source"] = feed["name"]
                        new_filings.append(case)

            except Exception as e:
                print(f"Error checking {feed['name']}: {e}")

            time.sleep(5)

        return new_filings

Erros comuns na coleta de dados jurídicos

Problema Causa Correção
CAPTCHA de imagem falha repetidamente Texto distorcido Descarte a imagem e peça uma nova tentativa
PACER bloqueia o acesso Limite de requisições excedido Aguarde 30 minutos e reduza a frequência das requisições
Detalhes do processo incompletos Conteúdo atrás de paywall Reserve orçamento para taxas por página quando necessário
Busca não retorna resultados Página de CAPTCHA devolvida no lugar dos dados Verifique se há CAPTCHA na resposta antes de fazer o parsing
Monitoramento de processos perde atualizações Intervalo de verificação longo demais Aumente a frequência de verificação do feed

Onde o CAPTCHA aparece na pesquisa jurídica automatizada

Fonte Tipo de CAPTCHA Dados Quem usa
PACER reCAPTCHA v2 Processos judiciais federais (EUA) Equipes de litígio
Tribunais estaduais (EUA) CAPTCHA de imagem / reCAPTCHA Registros de processos estaduais Advogados
SEC EDGAR reCAPTCHA v2 Arquivamentos corporativos Compliance
Bancos de dados de patentes reCAPTCHA v2 Registros de patentes Pesquisadores de PI
Portais regulatórios CAPTCHA de imagem Normas e orientações Compliance
Bancos de citações jurídicas reCAPTCHA v2 Citações de casos Legaltech
Diretórios de ordens de advogados reCAPTCHA v2 Registros profissionais Due diligence

Uso autorizado e compliance na coleta de dados jurídicos

  • A maior parte desses registros é pública, mas "público" não dispensa boas práticas.
  • Respeite o limite de requisições de cada sistema e identifique o worker no User-Agent quando o portal pedir.
  • Trate os dados coletados — nome das partes, número do processo, endereços — com o mesmo cuidado que qualquer outro dado pessoal.
  • Se o resultado alimenta um sistema com usuários no Brasil, considere as obrigações da LGPD sobre esse tratamento; para operações com base em Portugal, o equivalente é o RGPD.
  • Nenhuma das duas leis muda a legalidade de consultar um registro público — mudam as regras de como você armazena e usa o que coletou.

Perguntas frequentes

O CaptchaAI resolve os CAPTCHAs de imagem usados pelos tribunais estaduais?

Sim. Image/OCR CAPTCHA é um tipo com suporte total na API, junto com reCAPTCHA v2 — a combinação mais comum nos portais judiciais e regulatórios dos EUA.

Preciso rodar a coleta atrás de proxy para não ser bloqueado no PACER ou no SEC EDGAR?

Depende do volume. Para poucas páginas por dia normalmente não é necessário. Em coleta de alto volume, um proxy dedicado ajuda a espaçar as requisições e evitar bloqueios por limite de taxa — isso é decisão de infraestrutura, independente da resolução do CAPTCHA.

Como orçar as taxas por página do PACER numa coleta em massa?

O PACER cobra por página consultada, não por CAPTCHA resolvido. Estime o custo pelo número de documentos antes de rodar uma coleta grande e considere o RECAP, arquivo gratuito de documentos já baixados por outros usuários.

É permitido automatizar a consulta a registros judiciais e regulatórios públicos?

Registros públicos são, em geral, acessíveis por automação. O ponto de atenção não é o acesso em si, e sim respeitar os limites de taxa e os termos de uso de cada sistema — o PACER cobra a mesma taxa por página independentemente do método de acesso.

Rodar vários monitores em paralelo consome mais threads do plano CaptchaAI?

Sim — cada resolução simultânea ocupa uma thread do plano. O BASIC (US$ 15/mês, 5 threads) atende poucos feeds; para monitorar dezenas de fontes ao mesmo tempo, o STANDARD (US$ 30/mês, 15 threads) ou um plano superior evita fila de espera.


Guias relacionados


Configure a API da CaptchaAI e consulte jurisprudência no PACER sem travar no CAPTCHA — obtenha sua chave de API e automatize a pesquisa jurídica de ponta a ponta.

Os comentários estão desativados para este artigo.