Uma coleta de dados sociais raramente quebra no parser. Ela quebra na terceira hora, quando a plataforma decide que aquele padrão de acesso merece um desafio e o script passa a receber HTML de CAPTCHA no lugar do perfil. A saída não é insistir mais rápido: é baixar o ritmo, alinhar a rota de saída ao tráfego esperado e resolver o desafio por API.
Este guia monta esse fluxo em Python, do escopo autorizado ao código que envia o desafio à CaptchaAI e devolve o token à página. Os tipos daqui — reCAPTCHA v2, reCAPTCHA v3 e Cloudflare Turnstile — são os que a CaptchaAI resolve; hCaptcha e FunCaptcha não são suportados.
Onde o CAPTCHA aparece na coleta de dados sociais
O desafio quase nunca é o primeiro obstáculo: ele entra depois de um gatilho — volume por IP, sessão longa demais, buscas repetidas com o mesmo cookie. O tipo exibido define se o coletor precisa do fluxo de token do reCAPTCHA, do Turnstile ou dos dois.
| Plataforma | Tipo mais comum | Gatilho típico |
|---|---|---|
| reCAPTCHA v2 | Login, busca, acesso a perfil | |
| reCAPTCHA v2 | Login, buscas repetidas | |
| Twitter/X | Cloudflare Turnstile | Login, acesso à API |
| TikTok | reCAPTCHA v3 | Visualização de perfil, busca |
| Cloudflare Turnstile | Coleta de perfis públicos | |
| reCAPTCHA v2 | Login, navegação intensa |
Delimite o escopo autorizado antes de escrever o coletor
Dado público não é dado livre de obrigações: a LGPD trata perfis, biografias e posts identificáveis como dados pessoais mesmo abertos na web. Em Portugal, vale a mesma leitura sob o RGPD.
- Escreva a finalidade antes do primeiro
requests.get: pesquisa de mercado, monitoramento da marca própria, estudo acadêmico aprovado. - Colete só os campos que a finalidade exige, agregue cedo e defina prazo de retenção.
- Respeite os Termos de Serviço e os limites de requisição da plataforma.
- Registre o que foi coletado, quando e por qual rota: auditoria interna e um pedido da ANPD pedem o mesmo log.
Ritmo de requisições: o ajuste que mais reduz CAPTCHA
Resolver desafio por API é o plano B; o plano A é não provocar tantos. Comece conservador, meça a taxa de desafios por 100 requisições e só então aperte.
| Plataforma | Intervalo seguro | Sessão máxima |
|---|---|---|
| 1 requisição / 10 s | 5 min, depois pausa | |
| 1 requisição / 5 s | 10 min | |
| Twitter/X | 1 requisição / 3 s | 15 min |
| TikTok | 1 requisição / 5 s | 5 min |
| 1 requisição / 10 s | 5 min | |
| 1 requisição / 2 s | 30 min |
Coletor de pesquisa social em Python
A classe abaixo faz três coisas: mantém a sessão, detecta que a resposta virou um desafio e o resolve antes de reenviar. solve_captcha envia a tarefa para in.php e consulta res.php até o token ficar pronto; o mesmo par de endpoints serve reCAPTCHA e Turnstile, mudando só o method.
import requests
import time
import re
CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"
def solve_captcha(method, sitekey, pageurl, **kwargs):
data = {
"key": CAPTCHAAI_KEY,
"method": method,
"googlekey": sitekey,
"pageurl": pageurl,
"json": 1,
}
data.update(kwargs)
resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data=data)
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,
})
r = result.json()
if r["request"] != "CAPCHA_NOT_READY":
return r["request"]
raise TimeoutError("Solve timeout")
class SocialMediaResearcher:
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 (iPhone; CPU iPhone OS 17_5 like Mac OS X) "
"AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 "
"Mobile/15E148 Safari/604.1",
"Accept-Language": "en-US,en;q=0.9",
})
def authenticate(self, login_url, credentials, sitekey):
"""Login with CAPTCHA handling."""
# Load login page
self.session.get(login_url)
# Solve CAPTCHA
token = solve_captcha("userrecaptcha", sitekey, login_url)
# Submit login
resp = self.session.post(login_url, data={
**credentials,
"g-recaptcha-response": token,
})
return resp.status_code == 200
def collect_profiles(self, profile_urls):
"""Collect public profile data with CAPTCHA handling."""
profiles = []
for url in profile_urls:
try:
resp = self.session.get(url, timeout=30)
# Handle CAPTCHA if triggered
if self._has_captcha(resp.text):
resp = self._handle_captcha(resp.text, url)
profiles.append({
"url": url,
"data": self._parse_profile(resp.text),
"status": "success",
})
time.sleep(5) # Slow down between profiles
except Exception as e:
profiles.append({
"url": url,
"error": str(e),
"status": "failed",
})
return profiles
def _has_captcha(self, html):
return any(tag in html.lower() for tag in [
'data-sitekey', 'g-recaptcha', 'cf-turnstile',
'challenge-platform', 'captcha',
])
def _handle_captcha(self, html, url):
match = re.search(r'data-sitekey="([^"]+)"', html)
if not match:
return self.session.get(url)
sitekey = match.group(1)
if 'cf-turnstile' in html:
token = solve_captcha("turnstile", sitekey, url)
return self.session.post(url, data={"cf-turnstile-response": token})
else:
token = solve_captcha("userrecaptcha", sitekey, url)
return self.session.post(url, data={"g-recaptcha-response": token})
def _parse_profile(self, html):
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
return {
"name": self._safe_text(soup, "h1, .profile-name"),
"bio": self._safe_text(soup, ".bio, .profile-bio"),
"followers": self._safe_text(soup, "[data-followers], .followers"),
"posts": self._safe_text(soup, "[data-posts], .posts-count"),
}
def _safe_text(self, soup, selector):
el = soup.select_one(selector)
return el.get_text(strip=True) if el else ""
Pesquisa por hashtag e tendências
Na coleta por hashtag é a paginação que denuncia o robô: dezenas de páginas iguais, mesmo intervalo, mesmo cabeçalho. Mantenha o time.sleep entre as páginas e trate o desafio dentro do laço, sem reiniciar a sessão.
def research_hashtag(hashtag, platform_url, pages=5):
"""Collect posts for a specific hashtag."""
researcher = SocialMediaResearcher(
proxy="http://user:[email protected]:5000"
)
all_posts = []
for page in range(pages):
url = f"{platform_url}/explore/tags/{hashtag}?page={page}"
resp = researcher.session.get(url, timeout=30)
if researcher._has_captcha(resp.text):
resp = researcher._handle_captcha(resp.text, url)
from bs4 import BeautifulSoup
soup = BeautifulSoup(resp.text, "html.parser")
posts = soup.select(".post-item, article")
for post in posts:
all_posts.append({
"text": post.get_text(strip=True)[:500],
"hashtag": hashtag,
"page": page,
})
time.sleep(5)
return all_posts
Monitoramento de menções à marca
Cenário comum em agências de social listening no Brasil: um scan diário de madrugada cruzando palavras-chave em duas ou três plataformas, com relatório em JSON para o cliente. Rodar os workers em sa-east-1 (São Paulo) corta o RTT por desafio.
import json
from datetime import datetime
class BrandMonitor:
def __init__(self, brand_name, keywords, proxy=None):
self.brand = brand_name
self.keywords = keywords
self.researcher = SocialMediaResearcher(proxy=proxy)
def daily_scan(self, platform_urls):
"""Run daily brand mention scan across platforms."""
report = {
"brand": self.brand,
"date": datetime.now().isoformat(),
"platforms": {},
}
for name, url in platform_urls.items():
mentions = []
for keyword in self.keywords:
search_url = f"{url}/search?q={keyword}"
try:
resp = self.researcher.session.get(search_url, timeout=30)
if self.researcher._has_captcha(resp.text):
resp = self.researcher._handle_captcha(
resp.text, search_url,
)
from bs4 import BeautifulSoup
soup = BeautifulSoup(resp.text, "html.parser")
results = soup.select(".search-result, .post")
mentions.append({
"keyword": keyword,
"count": len(results),
})
time.sleep(5)
except Exception as e:
mentions.append({
"keyword": keyword,
"error": str(e),
})
report["platforms"][name] = mentions
return report
# Usage
monitor = BrandMonitor(
brand_name="CaptchaAI",
keywords=["captchaai", "captcha ai", "captcha solver"],
proxy="http://user:[email protected]:5000",
)
report = monitor.daily_scan({
"twitter": "https://twitter-alternative.example.com",
"reddit": "https://www.reddit.com",
})
print(json.dumps(report, indent=2))
Alinhe a rota de saída ao tráfego que a plataforma espera
Não existe rota mágica; existe coerência. Um User-Agent de iPhone saindo de uma faixa de datacenter é uma contradição que qualquer detector lê em milissegundos. Use egress autorizado, com rotação dentro do seu pool.
- Instagram e TikTok esperam acesso de app móvel: egress em rede celular autorizada destoa menos.
- Facebook e Twitter/X marcam faixas de datacenter com rigor — prefira banda larga contratada.
- LinkedIn espera IPs de desktop e corporativos, típicos de ISP contratado.
- Reddit limita por IP: rotacione dentro do pool e mantenha o intervalo.
Quanto custa manter essa coleta de pé
A conta da CaptchaAI não é por desafio resolvido: os planos são por thread simultânea, com resoluções ilimitadas no mês. Uma thread é um desafio em andamento; quando ele termina, ela pega o próximo. O que dimensiona o plano é a concorrência do coletor.
- BASIC (US$ 15/mês, 5 threads) — scan diário de marca, execução sequencial.
- STANDARD (US$ 30/mês, 15 threads) — hashtags em várias plataformas em paralelo.
- ADVANCE (US$ 90/mês, 50 threads) — pesquisa contínua com dezenas de workers.
Quando a coleta trava: diagnóstico rápido
| Sintoma | Causa provável | O que fazer |
|---|---|---|
| CAPTCHA em toda requisição | IP marcado | Rotacione o egress, aumente o intervalo |
| Conta bloqueada | Ações demais na sessão | Reduza a frequência, distribua no dia |
| Página vazia | Conteúdo atrás do login | Autentique antes de percorrer a lista |
| Ciclo de desafio do Cloudflare | Sinais de navegador inconsistentes | Navegador real com Puppeteer em QA |
| Conteúdo diferente do navegador | Idioma, região ou cookie divergentes | Alinhe a rota e o Accept-Language |
Perguntas frequentes
Quais tipos de CAPTCHA a CaptchaAI resolve nesse fluxo?
Os três das tabelas acima: reCAPTCHA v2, reCAPTCHA v3 e Cloudflare Turnstile. Há ainda GeeTest v3, imagem e OCR, grade de imagens e BLS. hCaptcha e FunCaptcha não são suportados; GeeTest v4 está como "em breve".
Como dimensiono o plano para um scan diário?
Conte a concorrência, não o volume. Com 5 workers em paralelo, 5 threads dão conta; com 40, o degrau é o ADVANCE. Como as resoluções são ilimitadas por thread, mais frequência não muda a fatura.
A LGPD se aplica a dados públicos de redes sociais?
Sim. Estar público não retira o dado da esfera da LGPD quando ele identifica alguém. Defina finalidade, minimize os campos e agregue cedo. Para o seu caso concreto, consulte o jurídico da empresa.
Preciso de um navegador headless ou o requests basta?
Na maioria dos casos requests com sessão persistente resolve e gasta menos CPU. O headless só se justifica quando a página monta o conteúdo por JavaScript ou o desafio depende de um callback.
E se a plataforma oferecer uma API oficial?
Use a API oficial: mais estável, mais barata em manutenção e alinhada aos Termos de Serviço. Reserve a coleta com CAPTCHA para o que a API não expõe.
Leituras relacionadas
- Rotação de rede móvel na resolução de CAPTCHA
- Sessão de navegador entre desafios
- Isolamento de perfis de navegador
Mantenha sua pesquisa em redes sociais rodando sem parar a cada desafio — obtenha sua chave da CaptchaAI e resolva o CAPTCHA dentro do próprio coletor.