Use Cases

CAPTCHA İşleme ile Sosyal Medya Araştırma Verisi Toplama

Halka açık sosyal medya verisi toplayan bir araştırma işi, çoğu zaman ayrıştırma hatası yüzünden değil, akışın ortasında beliren bir doğrulama ekranı yüzünden durur. Pratik cevap şu: CAPTCHA'yı istisna olarak değil, toplayıcınızın normal bir adımı olarak modelleyin. Sayfayı alın, doğrulama var mı diye bakın, varsa token'ı API ile çözün, aynı oturum üzerinden gönderin ve kaldığınız yerden devam edin. Aşağıdaki Python iskeleti bunu yapıyor: reCAPTCHA v2, reCAPTCHA v3 ve Cloudflare Turnstile'ı CaptchaAI üzerinden çözüyor ve tek bir profil takıldığında çalışmanın tamamını durdurmuyor.


Hangi platformda hangi CAPTCHA çıkıyor

Doğrulamanın türü, toplayıcınızın hangi kod yolunu izleyeceğini belirler.

Platform CAPTCHA türü Ne zaman çıkar Bağlam
Instagram reCAPTCHA v2 Giriş, arama, profil erişimi İstek sınırlama
Facebook reCAPTCHA v2 Giriş, tekrarlanan aramalar Güvenlik kontrol noktası
Twitter/X Cloudflare Turnstile Giriş, API erişimi Bot önleme
TikTok reCAPTCHA v3 Profil görüntüleme, arama Trafik kalitesi puanı
LinkedIn Cloudflare doğrulama akışı Yoğun profil gezinmesi Bot tespiti
Reddit reCAPTCHA v2 Giriş, yoğun gezinme Kötüye kullanım önleme

Bu listedeki türlerin tamamı CaptchaAI tarafından destekleniyor. Kapsam dışını da baştan bilin: hCaptcha ve FunCaptcha desteklenmiyor, GeeTest v4 için yalnızca "çok yakında" ifadesi geçerli. Bir platform bu türlere geçtiyse, o kaynağı iş akışınızın kapsamından çıkarın.


Toplamaya başlamadan önce: kapsam ve KVKK

Türkiye'de çalışan bir araştırma ekibi için ilk karar teknik değil hukuki: hangi alanları topluyorsunuz ve neden. Bir profilin herkese açık olması, oradaki adın, biyografinin veya konum bilgisinin kişisel veri olmaktan çıktığı anlamına gelmez — KVKK kapsamı, verinin görünür olmasına değil, kime ait olduğuna bakar.

Pratikte üç kural işe yarıyor: alan listesini daraltın (sayım için gönderi metni yeterliyse kullanıcı adını hash'leyin), saklama süresini projenin başında sınırlayın ve platformun kullanım koşullarına uyun. CAPTCHA çözümü bir izin belgesi değil, yetkili toplama akışınızın kesintisiz çalışmasını sağlayan bir adımdır.


Toplayıcının CAPTCHA farkında iskeleti

Tasarımın özü tek bir fikirde toplanıyor: her yanıtı alırken içinde doğrulama işareti olup olmadığını kontrol edin. data-sitekey, g-recaptcha veya cf-turnstile görüyorsanız sitekey'i sayfadan okuyun, uygun method ile CaptchaAI'ye gönderin ve dönen token'ı doğru alana yazın: reCAPTCHA için g-recaptcha-response, Turnstile için cf-turnstile-response.

Sorgulama döngüsünü gerçekçi tutun: res.php yanıtı CAPCHA_NOT_READY olduğu sürece bekleyin, ama zaman aşımına düşen tek bir profil listenin geri kalanını durdurmasın. Her URL kendi try bloğunda çalışır ve sonucu success ya da failed etiketiyle raporlar.

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 ""

Buradaki SocialMediaResearcher sınıfı tek bir requests.Session üzerinden ilerliyor. Bunun önemi şu: çözülen token ile devam eden istek aynı oturumda olmazsa, doğrulama akışı en baştan tetiklenir ve kendinizi sonu gelmeyen bir döngüde bulursunuz.


Hashtag ve trend verisini sayfalayarak toplama

Trend araştırmasında hacim, sayfalama döngüsünden gelir — ve doğrulama genelde ikinci ya da üçüncü sayfada devreye girer. Aynı kontrol mantığını sayfa döngüsünün içine koyun, her sayfa arasına gecikme bırakın ve topladığınız metni kısaltarak saklayın; ham HTML biriktirmenin analiz açısından bir faydası yok.

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

Marka anmalarını günlük taramaya bağlama

Marka takibi tekrarlanabilirlik ister: aynı anahtar kelimeler, aynı platformlar, her gün aynı saatte. Zamanlamayı Europe/Istanbul saatine göre kurun ve çıktıyı tarih damgalı JSON olarak saklayın; sayım düştüğünde bunun gerçek bir düşüş mü yoksa toplama hatası mı olduğunu ancak böyle ayırt edersiniz.

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))

Anahtar kelime başına hata alanını raporda tutmak sessiz veri kaybını önler: üst üste failed görüyorsanız sorun genellikle çözümde değil istek ritmindedir.


İstek hızı ve oturum bütçesi

Toplama hızını CAPTCHA'ya rağmen değil, CAPTCHA'yı hesaba katarak planlayın. Aşağıdaki değerler saha gözlemlerine dayanır ve platform davranışına göre değişebilir; kendi ölçümünüzle güncelleyin.

Platform Güvenli istek aralığı Oturum uzunluğu
Instagram 10 saniyede 1 istek En fazla 5 dakika, sonra ara verin
Facebook 5 saniyede 1 istek En fazla 10 dakika
Twitter/X 3 saniyede 1 istek En fazla 15 dakika
TikTok 5 saniyede 1 istek En fazla 5 dakika
LinkedIn 10 saniyede 1 istek En fazla 5 dakika
Reddit 2 saniyede 1 istek En fazla 30 dakika

Proxy kullanıyorsanız çıkış noktasını araştırdığınız kitlenin bölgesiyle tutarlı tutun ve Accept-Language başlığını aynı bölgeye göre ayarlayın; içerik farklılıkları çoğu zaman engellemeden değil, bölgesel varyasyondan kaynaklanır. Ayrıntılı yapılandırma için proxy kullanımı ve çözüm başarısı rehberine bakabilirsiniz.


Eşzamanlılık ve maliyet: hangi plan yeter?

CaptchaAI thread tabanlı faturalandırılır: bir thread, aynı anda işlenen tek bir CAPTCHA demektir ve plan içindeki çözüm sayısı sınırsızdır. Yani maliyeti belirleyen soru "kaç CAPTCHA çözeceğim" değil, "aynı anda kaç tanesini bekleteceğim".

Hesabı en kötü durum üzerinden yapın: Cloudflare Turnstile 10 saniyenin altında, reCAPTCHA v3 4 saniyenin altında temizlenir, reCAPTCHA v2 için tavan 60 saniyedir. Tek makineli günlük bir marka taraması genellikle BASIC ($15/ay, 5 thread) ile döner; paralel platform taraması için STANDARD ($30/ay, 15 thread), üretim ölçekli bir pipeline için ADVANCE ($90/ay, 50 thread) uygundur.

Türkiye'deki ekipler için ek bir avantaj var: fiyat USD üzerinden ve aylık sabittir. Çözüm başına ücretlendirmede hacim arttıkça bütçe kayarken, thread tabanlı planda ay başında bildiğiniz rakam ay sonunda da aynıdır.


Sorun giderme

Sorun Olası sebep Ne yapmalı
Her istekte CAPTCHA çıkıyor Çıkış IP'niz işaretlenmiş İstek aralığını artırın, çıkış noktanızı ve oturum uzunluğunu yeniden yapılandırın
Boş sayfa dönüyor İçerik giriş adımının arkasında Önce kimlik doğrulamasını tamamlayın, sonra profil isteklerine geçin
Doğrulama akışı döngüye giriyor Token farklı bir oturumdan gönderiliyor Aynı requests.Session üzerinden devam edin
Token çözüldü ama reddedildi Token'ın süresi doldu ya da sitekey eski sitekey'i sayfadan yeniden okuyun ve token'ı çözümden hemen sonra gönderin
Tarayıcıdaki içerikten farklı sonuç Bölge ve dil farkı Accept-Language değerini ve çıkış bölgesini hedef kitleyle eşleştirin

Oturumların birden fazla çalıştırma boyunca ayakta kalması gerekiyorsa tarayıcı oturumu kalıcılığı rehberi ve tarayıcı profili izolasyonu ile CaptchaAI entegrasyonu bu iskeletin doğal devamıdır.


Sık sorulan sorular

CaptchaAI hangi CAPTCHA türlerini çözüyor, hCaptcha destekleniyor mu?

hCaptcha ve FunCaptcha desteklenmiyor; GeeTest v4 için yalnızca "çok yakında" ifadesi geçerli. Bu iş akışında geçen reCAPTCHA v2 (görünmez ve Enterprise varyantları dâhil), reCAPTCHA v3, Cloudflare Turnstile, Cloudflare doğrulama akışı ve GeeTest v3 destekleniyor. CaptchaFox (beta), Friendly Captcha (beta) ve Lemin (beta) ise beta aşamasındadır.

Araştırma projem için kaç thread gerekir?

Eşzamanlı olarak beklettiğiniz CAPTCHA sayısı kadar. "Aynı anda kaç toplayıcı işçim doğrulama bekliyor?" sorusunu yanıtlayın: beş paralel işçilik bir tarama BASIC ($15/ay, 5 thread) ile başlar, kuyrukta bekleme süresi büyümeye başladığında bir üst plana geçin.

Token'ı hangi alana yazmam gerekiyor?

reCAPTCHA ailesinde g-recaptcha-response, Cloudflare Turnstile'da cf-turnstile-response. Alan adlarını karıştırmak, çözüm doğru olsa bile isteğin reddedilmesinin en sık sebebidir. Token'ı aldıktan sonra bekletmeyin — kısa ömürlüdür ve süresi dolan bir token yeniden çözüm gerektirir.

Topladığım profil verileri KVKK kapsamına girer mi?

Kişiyi doğrudan ya da dolaylı tanımlıyorsa evet; verinin herkese açık olması bunu değiştirmez. Gerekçenizi belgeleyin, gereksiz alanları hiç almayın ve yalnızca toplam sayım üretecekseniz kimlik alanlarını toplama anında anonimleştirin.


İlgili kılavuzlar


Araştırma toplayıcınızın doğrulama adımını çalışır hâle getirin — CaptchaAI anahtarınızı alın ve platform CAPTCHA'larını otomatik çözüme bağlayın.

Bu makale için yorumlar devre dışı bırakılmıştır.