¿Recopilas datos públicos de redes sociales para un estudio de mercado y cada búsqueda acaba en un CAPTCHA? Instagram y Reddit muestran reCAPTCHA v2, X levanta Cloudflare Turnstile y TikTok evalúa con reCAPTCHA v3. CaptchaAI resuelve esos tres tipos por API, así que tu scraper obtiene el token y sigue adelante.
Qué CAPTCHA usa cada plataforma social
Cada plataforma dispara un tipo distinto y en momentos distintos:
| Plataforma | Tipo de CAPTCHA | Cuándo aparece | Motivo |
|---|---|---|---|
| reCAPTCHA v2 | Login, búsqueda, acceso a perfil | Límite de solicitudes | |
| reCAPTCHA v2 | Login, búsquedas repetidas | Punto de control de seguridad | |
| Twitter/X | Cloudflare Turnstile | Login, acceso a la API | Prevención de bots |
| TikTok | reCAPTCHA v3 | Vistas de perfil, búsqueda | Calidad del tráfico |
| Cloudflare Challenge | Extracción de perfiles | Detección de bots | |
| reCAPTCHA v2 | Login, navegación intensa | Prevención de abuso |
Un caso típico: seguimiento de marca desde una agencia
Una agencia en Ciudad de México sigue las menciones de una marca de retail en Instagram, X y Reddit para un informe semanal. Tras varias búsquedas seguidas, Instagram levanta reCAPTCHA v2 y X un Cloudflare Turnstile, y el trabajo se detiene. Con CaptchaAI resolviéndolos por API, el script recorre las plataformas sin intervención. Trabaja solo con datos públicos y respeta los términos de servicio y la normativa aplicable (RGPD, LOPDGDD, LFPDPPP).
Scraper base para investigación social
La función solve_captcha envía la tarea a in.php y consulta res.php hasta obtener el token.
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 ""
El detalle clave: si el HTML trae cf-turnstile se usa el método turnstile y el campo cf-turnstile-response; en el resto, userrecaptcha.
Investigación de hashtags y tendencias
Recorrer un hashtag reutiliza la misma comprobación de CAPTCHA en cada página:
def research_hashtag(hashtag, platform_url, pages=5):
"""Collect posts for a specific hashtag."""
researcher = SocialMediaResearcher(
proxy="http://user:pass@mobile.proxy.com: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
Vigilancia de menciones de marca
Un barrido diario por palabra clave y plataforma, con el CAPTCHA resuelto dentro del bucle:
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:pass@mobile.proxy.com:5000",
)
report = monitor.daily_scan({
"twitter": "https://twitter-alternative.example.com",
"reddit": "https://www.reddit.com",
})
print(json.dumps(report, indent=2))
Errores comunes y soluciones
| Problema | Causa | Solución |
|---|---|---|
| CAPTCHA en cada solicitud | IP marcada | Rota la IP y usa una red móvil autorizada |
| Cuenta bloqueada | Demasiadas acciones seguidas | Reduce la frecuencia y respeta los límites |
| Página vacía | Contenido detrás del login | Autentícate primero |
| Bucle de Cloudflare Challenge | Señales del navegador inconsistentes | Usa un navegador headless con configuración estándar o Puppeteer |
| Contenido distinto al del navegador | Diferencias de ubicación o cookies | Ajusta la geografía de la salida de red al público |
Ritmo de solicitudes recomendado
El ritmo evita que te muestren el CAPTCHA en cada página:
| Plataforma | Frecuencia segura | Duración de la sesión |
|---|---|---|
| 1 solicitud cada 10 s | Máximo 5 min | |
| 1 solicitud cada 5 s | Máximo 10 min | |
| Twitter/X | 1 solicitud cada 3 s | Máximo 15 min |
| TikTok | 1 solicitud cada 5 s | Máximo 5 min |
| 1 solicitud cada 10 s | Máximo 5 min | |
| 1 solicitud cada 2 s | Máximo 30 min |
Qué salida de red usar por plataforma
Cada plataforma espera un perfil de red distinto:
| Plataforma | Salida de red recomendada | Por qué |
|---|---|---|
| Móvil (4G) | Espera tráfico móvil | |
| Residencial | Marca IP de datacenter | |
| Twitter/X | Residencial | Cloudflare bloquea datacenters |
| TikTok | Móvil (4G) | Diseñado para móvil |
| ISP residencial | Espera IP de escritorio | |
| Residencial rotativa | Límites por IP |
Preguntas frecuentes
¿Es legal recopilar datos públicos de redes sociales para investigación?
Depende. La recopilación de datos públicos para investigación no comercial es habitual, y varios tribunales han considerado que extraer datos públicos no infringe la CFAA. Aun así, respeta los términos de servicio y la normativa de protección de datos aplicable.
¿Qué tipos de CAPTCHA resuelve CaptchaAI en estas plataformas?
Cubre reCAPTCHA v2 (Instagram, Facebook, Reddit), reCAPTCHA v3 (TikTok), Cloudflare Turnstile (X) y Cloudflare Challenge (LinkedIn). No resuelve hCaptcha ni FunCaptcha.
¿Cuánto cuesta resolver los CAPTCHA a este volumen?
CaptchaAI cobra por thread concurrente, no por resolución. El plan BASIC ($15/mes, 5 threads) cubre un monitoreo diario modesto y STANDARD ($30/mes, 15 threads) suma capacidad simultánea. Todos incluyen resoluciones ilimitadas por thread: un costo predecible en USD.
Guías relacionadas
- Red móvil autorizada para resolver CAPTCHA
- Persistencia de sesión del navegador con CAPTCHA
- QA autorizado de tu propio flujo de scraping
Recopila datos de investigación social sin frenar tu pipeline: consigue tu clave de CaptchaAI y resuelve cada CAPTCHA automáticamente.