Se o seu sistema guarda, compartilha ou publica fotos com pessoas ou carros, ele está tratando dados pessoais. Pela LGPD, rosto e placa identificam alguém (art. 5º, I), e os metadados EXIF ainda guardam a localização GPS de onde a foto foi tirada.
Este tutorial mostra como anonimizar imagens em lote com uma API: localizar rostos e placas, borrar de forma irreversível e remover os metadados. Tudo com curl ou Python, sem treinar modelo e sem GPU.
O que você vai precisar
- Uma conta gratuita na Apify (o plano gratuito inclui US$ 5 de uso por mês)
- O token da API, em Settings → API & Integrations
- Python 3.9+ com
apify-clienterequests
pip install apify-client requests
export APIFY_TOKEN="seu_token_aqui"
Vamos usar o Image Anonymizer, uma API que detecta rostos e placas (com detector ajustado para placas brasileiras, Mercosul e modelo antigo), aplica o borrão e devolve a imagem sem EXIF.
1. Primeira chamada com curl
O endpoint run-sync-get-dataset-items roda a anonimização e devolve o resultado na mesma resposta. Serve para lotes pequenos, que terminam em até 5 minutos.
curl -X POST \
"https://api.apify.com/v2/acts/adorable_partial~image-anonymizer/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"imageUrls": ["https://upload.wikimedia.org/wikipedia/commons/thumb/5/52/Car_from_Sankt_Gallen.jpg/1280px-Car_from_Sankt_Gallen.jpg"],
"method": "blur"
}'
Repare que o token vai no cabeçalho Authorization, não na URL. Assim ele não fica gravado em logs de proxy nem no histórico do terminal de quem vê a URL.
A resposta é uma lista, com um item por imagem:
[
{
"sourceUrl": "https://upload.wikimedia.org/.../Car_from_Sankt_Gallen.jpg",
"outputUrl": "https://api.apify.com/v2/key-value-stores/.../records/anonymized-00001.jpg?signature=...",
"width": 1280,
"height": 960,
"facesBlurred": 0,
"platesBlurred": 1,
"metadataRemoved": true,
"faces": [],
"plates": [{ "x1": 474, "y1": 717, "x2": 801, "y2": 843, "score": 1.0 }]
}
]
O outputUrl é a imagem anonimizada. faces e plates trazem as coordenadas de cada região coberta, úteis para auditoria.
2. Lote em Python, baixando as imagens
Para lotes maiores, use o cliente Python. Ele inicia a execução, espera terminar e lê os resultados.
import os
from pathlib import Path
import requests
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
imagens = [
"https://exemplo.com/fotos/fachada-01.jpg",
"https://exemplo.com/fotos/evento-02.png",
# ... centenas de URLs
]
run = client.actor("adorable_partial/image-anonymizer").call(
run_input={
"imageUrls": imagens,
"blurFaces": True,
"blurPlates": True,
"method": "blur", # "blur", "pixelate" ou "solid"
"detectSmallFaces": True, # pega rostos pequenos em multidões
"outputFormat": "jpeg",
},
max_total_charge_usd=2, # teto de gasto desta execução
)
saida = Path("anonimizadas")
saida.mkdir(exist_ok=True)
for i, item in enumerate(client.dataset(run["defaultDatasetId"]).iterate_items(), 1):
if "error" in item:
print(f"falhou: {item['sourceUrl']} -> {item['error']}")
continue
destino = saida / f"{i:05d}.jpg"
destino.write_bytes(requests.get(item["outputUrl"], timeout=60).content)
print(f"{destino}: {item['facesBlurred']} rosto(s), {item['platesBlurred']} placa(s)")
O max_total_charge_usd é um teto de gasto: se o lote ficar mais caro que isso, a API para de processar em vez de passar do limite. Imagens que falham voltam com o campo error e não são cobradas.
3. Opções disponíveis
| Campo | Padrão | O que faz |
|---|---|---|
imageUrls |
obrigatório | Links das imagens (JPEG, PNG, WebP, BMP, TIFF). Aceita links públicos do Google Drive e do Dropbox. |
blurFaces |
true |
Detecta e cobre rostos. |
blurPlates |
true |
Detecta e cobre placas de veículos. |
method |
"blur" |
blur (borrão irreversível), pixelate (mosaico) ou solid (tarja preta). |
detectSmallFaces |
false |
Faz uma passada extra para rostos pequenos e distantes. Mais lento. |
paddingPercent |
20 |
Aumenta cada região detectada para cobrir cabelo, orelhas e moldura da placa. |
outputFormat |
"jpeg" |
jpeg, png ou webp. O EXIF é sempre removido. |
includeDetections |
true |
Inclui as coordenadas de rostos e placas no resultado. |
4. Imagens que estão no S3 ou em disco
A API recebe URLs, então imagens privadas precisam de um link temporário. No S3, gere URLs pré-assinadas com validade curta:
import boto3
s3 = boto3.client("s3")
chaves = ["vistorias/2026/09/carro-001.jpg", "vistorias/2026/09/carro-002.jpg"]
imagens = [
s3.generate_presigned_url(
"get_object",
Params={"Bucket": "meu-bucket", "Key": chave},
ExpiresIn=900, # 15 minutos
)
for chave in chaves
]
Depois é só passar a lista imagens para o código da seção 2. O link expira sozinho, e o bucket continua privado.
5. Automatizando o fluxo
Algumas formas de deixar a anonimização rodando sem intervenção:
- Agendamento: em Schedules, no Console da Apify, a execução roda num horário fixo, por exemplo toda noite.
- Webhook: configure um webhook para o evento de execução concluída. Seu sistema é avisado quando o lote termina e baixa as imagens.
- Sem código: há integrações prontas com n8n, Make e Zapier. Um fluxo comum é: foto nova numa pasta do Google Drive → anonimização → imagem salva em outra pasta.
Custos
São US$ 0,005 por imagem anonimizada, mais cerca de US$ 0,005 por execução. Mil imagens custam em torno de US$ 5. Imagens com erro não são cobradas.
Limitações
- Rostos de perfil acentuado, cobertos ou muito desfocados podem escapar. Em imagens críticas, revise uma amostra ou use
"method": "solid". - O detector de placas foi ajustado com placas brasileiras. Ele detecta muitas placas de outros países, mas a precisão nelas não foi medida.
- Crachás, uniformes, tatuagens e fachadas também podem identificar alguém, e não são tratados.
- Se você guardar a foto original, a cópia borrada pode continuar sendo dado pessoal: o art. 12 da LGPD considera reversível o processo que o próprio controlador consegue desfazer.
Resumo
Com uma chamada de API dá para tirar rostos, placas e localização GPS das imagens antes de armazenar, compartilhar ou publicar. É privacidade desde a concepção (LGPD, art. 46, § 2º) aplicada no código, e reduz o impacto de qualquer vazamento.
Texto informativo, não é orientação jurídica.
Top comments (0)