Verificar, para o universo de candidaturas registradas nas Eleições Gerais 2026, a hospedagem em território brasileiro dos sites próprios declarados à Justiça Eleitoral.
Este documento reproduz o entendimento da legislação tal como apresentado ao autor do projeto (inclusive via uma busca com resposta de IA, usada como ponto de partida). Não substitui parecer jurídico formal, antes de qualquer comunicação oficial ao TSE, recomenda-se validação por profissional do Direito Eleitoral quanto à redação exata vigente de cada dispositivo.
Toda a coleta usa exclusivamente a API pública do painel
"Divulgação de Candidaturas e Contas Eleitorais"
(https://divulgacandcontas.tse.jus.br/divulga/), a mesma que alimenta
o site oficial de consulta do TSE. Não há uso de nenhuma base paga,
vazada ou não pública.
Endpoints usados (descobertos por engenharia reversa das chamadas de rede feitas pela própria SPA oficial do TSE, navegando manualmente pela interface):
| Endpoint | Uso |
|---|---|
GET /rest/v1/eleicao/eleicao-atual?idEleicao={id} | Estrutura nacional: todas as UFs, cargos e contagem de candidatos |
GET /rest/v1/candidatura/listar/{ano}/{uf}/{id}/{cargo}/candidatos | Lista de candidatos de um cargo/UF |
GET /rest/v1/candidatura/buscar/{ano}/{uf}/{id}/candidato/{idCandidato} | Detalhe do candidato, incl. campo sites (endereços declarados) |
O domínio divulgacandcontas.tse.jus.br (e também www.tse.jus.br e
dadosabertos.tse.jus.br) está atrás de um WAF que retorna
HTTP 403 "Access Denied" para qualquer cliente que não seja um
navegador real renderizando a página, isso inclui curl, a biblioteca
requests do Python, e também o Playwright/Selenium rodando em modo
headless (mesmo com IP residencial brasileiro, mesmo mascarando
navigator.webdriver).
Testes realizados (ver histórico do projeto) mostraram que:
curl com headers de navegador, 403headless=True, com e sem flags anti-detecção, 403headless=False (janela real, mesmo processo,
mesma máquina, mesmo IP), 200, funciona normalmente
Conclusão prática: o bloqueio não é por IP/rede, é por alguma
característica de fingerprinting específica do modo headless do
Chromium (comum em soluções de bot management como Akamai/Cloudflare
Bot Manager). A solução adotada foi rodar um Chromium com interface
gráfica (headless=False) e fazer as chamadas de API via fetch()
dentro da própria página carregada, replicando exatamente o
comportamento de um usuário navegando pelo site. Ver
scripts/tse_client.py.
Essa exigência tem uma implicação prática importante: os crawlers deste projeto não podem rodar num servidor CI/CD puramente headless sem um display virtual (Xvfb ou equivalente), precisam de um ambiente com sessão gráfica disponível.
Script: scripts/discover_candidatos.py
sites, a lista de endereços eletrônicos que o próprio candidato
comunicou à Justiça Eleitoral (nos termos do art. 57-B, I).data/raw/candidatos_sites.csv, um
registro por candidato. Execução é resumível: candidatos já
presentes no CSV de saída são pulados numa nova execução.Universo coberto: 20.965 candidaturas nacionais nas Eleições Gerais 2026 (contagem obtida diretamente da API do TSE em 15/09/2026).
Script: scripts/analisar_sites.py (usa site_classifier.py e hosting_analysis.py)
O campo sites do TSE é um campo de texto livre por candidato, mistura
links de redes sociais (Instagram, Facebook, X/Twitter, TikTok, YouTube,
Kwai, Threads, LinkedIn, Telegram, WhatsApp, Discord), agregadores de
link (Linktree e similares), plataformas de financiamento coletivo
(QueroApoiar, Vakinha etc.) e, eventualmente, um domínio próprio do
candidato.
A regra de hospedagem no Brasil (art. 57-B) diz respeito ao "sítio do
candidato", um domínio sobre o qual o candidato tem controle/escolha
de hospedagem, não aos perfis hospedados por terceiros (Meta, Google,
X etc.), cuja infraestrutura não é decisão do candidato. Por isso a
etapa de classificação (site_classifier.py) separa essas categorias
antes de aplicar a análise de hospedagem, evitando falsos positivos
("Instagram não hospedado no Brasil" não é uma violação imputável ao
candidato).
Para cada "site próprio":
ip-api.com), obtendo
país, ISP/organização e ASN.hospedado_no_brasil = True se o código de país for BR.
Limitação crítica: geolocalização de IP não revela o servidor de
origem quando o site está atrás de um CDN/proxy global (Cloudflare,
Akamai, Fastly, Amazon CloudFront, Sucuri/Imperva etc.), o IP
resolvido é o do ponto de presença (PoP) mais próximo do requisitante,
não o do servidor real. Isso é extremamente comum em sites de
campanha, já que Cloudflare oferece plano gratuito e proteção contra
DDoS. Exemplo real encontrado durante o desenvolvimento deste projeto,
lula.com.br resolve para um IP da Cloudflare geolocalizado no
Canadá, o que, tomado ingenuamente, sugeriria hospedagem fora do
Brasil, mas na verdade só reflete a rede de borda da Cloudflare, sem
qualquer relação com onde o servidor de origem realmente está.
Por isso, hosting_analysis.py detecta a organização/ISP do IP contra
uma lista de provedores conhecidos de CDN/proxy e, quando identificado,
não afirma hospedado_no_brasil = False, marca o campo como
indeterminado (None) e sinaliza atras_de_cdn_proxy com o nome do
provedor. Só é reportado hospedado_no_brasil = False com confiança
quando o IP resolvido pertence claramente a um provedor de hospedagem
comum (não um CDN de borda) fora do Brasil. Mesmo assim, casos
limítrofes precisam de checagem manual (ex.: histórico de DNS para
tentar identificar a origem real por trás do CDN) antes de qualquer
conclusão a ser comunicada ao TSE.
sites é de texto livre, sujeito a erros de digitação
que podem impedir a extração correta do domínio).
Todo o código está no
repositório no GitHub.
Os dados brutos e processados (CSV) ficam versionados em data/,
permitindo auditoria externa de cada etapa. Ver
README.md
para instruções de execução.