Casos de Uso

Recopilación de datos de investigación de redes sociales con manejo de CAPTCHA

¿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
Instagram reCAPTCHA v2 Login, búsqueda, acceso a perfil Límite de solicitudes
Facebook 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
LinkedIn Cloudflare Challenge Extracción de perfiles Detección de bots
Reddit 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
Instagram 1 solicitud cada 10 s Máximo 5 min
Facebook 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
LinkedIn 1 solicitud cada 10 s Máximo 5 min
Reddit 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é
Instagram Móvil (4G) Espera tráfico móvil
Facebook Residencial Marca IP de datacenter
Twitter/X Residencial Cloudflare bloquea datacenters
TikTok Móvil (4G) Diseñado para móvil
LinkedIn ISP residencial Espera IP de escritorio
Reddit Residencial rotativa Límites por IP

Preguntas frecuentes

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

Recopila datos de investigación social sin frenar tu pipeline: consigue tu clave de CaptchaAI y resuelve cada CAPTCHA automáticamente.

Los comentarios están deshabilitados para este artículo.