بازگشت به وبلاگ

چگونه از شناسایی Cloudflare در هنگام استفاده از پروکسی عبور کنیم

Cloudflare درخواست‌های شما را از طریق پروکسی مسدود می‌کند؟ روش‌های فنی دور زدن تشخیص را بررسی می‌کنیم: از تنظیمات صحیح TLS تا استفاده از مرورگرهای بدون سر با مثال‌های واقعی.

📅۲۶ آذر ۱۴۰۴
```html

7 روش تأیید شده برای دور زدن تشخیص Cloudflare هنگام کار از طریق پروکسی

Cloudflare بیش از 20٪ از کل ترافیک وب را پردازش می‌کند و از یک سیستم چند لایه برای حفاظت در برابر ربات‌ها استفاده می‌کند. هنگام کار از طریق سرورهای پروکسی احتمال دریافت کپچا یا مسدود شدن به شدت افزایش می‌یابد. در این راهنما جنبه‌های فنی تشخیص و روش‌های عملی دور زدن که در سال 2024 کار می‌کنند را بررسی خواهیم کرد.

چگونه Cloudflare پروکسی و ربات‌ها را شناسایی می‌کند

Cloudflare از یک سیستم تحلیلی جامع استفاده می‌کند که ده‌ها پارامتر هر درخواست را بررسی می‌کند. درک مکانیزم‌های تشخیص، اولین قدم برای دور زدن موفقیت‌آمیز حفاظت است.

روش‌های اصلی تشخیص

TLS Fingerprinting: Cloudflare پارامترهای SSL/TLS handshake (cipher suites، افزونه‌ها، ترتیب آن‌ها) را تحلیل می‌کند. هر HTTP client یک "اثر انگشت" منحصر به فرد دارد. به عنوان مثال، Python requests از OpenSSL با مجموعه‌ای خاص از رمزها استفاده می‌کند که به راحتی از Chrome یا Firefox قابل تشخیص است.

هنگام تحلیل درخواست، Cloudflare TLS fingerprint را با User-Agent اعلام شده مطابقت می‌دهد. اگر شما Chrome 120 را مشخص کنید، اما پارامترهای TLS با Python requests مطابقت داشته باشد — این یک تشخیص فوری ربات است.

پارامتر بررسی چه چیزی تحلیل می‌شود ریسک تشخیص
TLS fingerprint Cipher suites، افزونه‌ها، نسخه TLS بالا
HTTP/2 fingerprint ترتیب هدرها، فریم‌های SETTINGS بالا
شهرت IP تاریخچه IP، تعلق به دیتا سنترها متوسط
چالش JavaScript اجرا JS، canvas fingerprint، WebGL بالا
تحلیل رفتاری الگوهای درخواست، زمان‌بندی، حرکات ماوس متوسط

از سال 2023، Cloudflare به طور فعال از یادگیری ماشین برای تحلیل الگوهای رفتاری استفاده می‌کند. این سیستم نه تنها پارامترهای فنی را پیگیری می‌کند، بلکه زمان‌های بین درخواست‌ها، توالی اقدامات کاربر، حرکات ماوس و اسکرول صفحه را نیز رصد می‌کند.

پنهان‌سازی TLS fingerprint

TLS fingerprinting — موثرترین روش تشخیص ربات‌ها است. HTTP client‌های استاندارد (requests، curl، axios) یک fingerprint ایجاد می‌کنند که نمی‌توان آن را با مرورگر واقعی اشتباه گرفت. راه حل — استفاده از کتابخانه‌های تخصصی که رفتار TLS مرورگرها را شبیه‌سازی می‌کنند.

استفاده از curl-impersonate

کتابخانه curl-impersonate — نسخه‌ای اصلاح شده از curl است که به طور دقیق TLS و HTTP/2 fingerprints مرورگرهای محبوب را کپی می‌کند. از Chrome، Firefox، Safari و Edge پشتیبانی می‌کند.

# نصب curl-impersonate
git clone https://github.com/lwthiker/curl-impersonate
cd curl-impersonate
make chrome-build

# استفاده با شبیه‌سازی Chrome 120
curl_chrome120 -x http://username:password@proxy.example.com:8080 \
  -H "Accept-Language: en-US,en;q=0.9" \
  https://example.com

Python: کتابخانه tls-client

برای Python یک wrapper به نام tls-client وجود دارد که از curl-impersonate در پس‌زمینه استفاده می‌کند و رابطی مشابه requests ارائه می‌دهد.

import tls_client

# ایجاد یک نشست با fingerprint Chrome 120
session = tls_client.Session(
    client_identifier="chrome_120",
    random_tls_extension_order=True
)

# تنظیم پروکسی
proxies = {
    'http': 'http://username:password@proxy.example.com:8080',
    'https': 'http://username:password@proxy.example.com:8080'
}

# اجرای درخواست
response = session.get(
    'https://example.com',
    proxies=proxies,
    headers={
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language': 'en-US,en;q=0.9',
        'Accept-Encoding': 'gzip, deflate, br',
        'DNT': '1',
        'Connection': 'keep-alive',
        'Upgrade-Insecure-Requests': '1'
    }
)

print(response.status_code)

مهم: هنگام استفاده از tls-client، بسیار مهم است که User-Agent در هدرها با client_identifier انتخاب شده مطابقت داشته باشد. عدم تطابق منجر به تشخیص فوری خواهد شد.

بررسی TLS fingerprint

قبل از شروع پارس کردن، توصیه می‌شود که TLS fingerprint خود را بررسی کنید. از سرویس‌های tls.peet.ws یا ja3er.com برای تحلیل استفاده کنید.

# بررسی fingerprint
response = session.get('https://tls.peet.ws/api/all')
print(response.json()['tls']['ja3'])

# مقایسه با fingerprint واقعی Chrome:
# https://kawayiyi.com/tls-fingerprint-database/

تنظیم صحیح HTTP headers

حتی با TLS fingerprint صحیح، هدرهای HTTP نادرست ربات را افشا می‌کنند. Cloudflare نه تنها وجود هدرها را تحلیل می‌کند، بلکه ترتیب، فرمت مقادیر و سازگاری منطقی آن‌ها را نیز بررسی می‌کند.

هدرهای الزامی برای Chrome

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
    'Accept-Language': 'en-US,en;q=0.9',
    'Accept-Encoding': 'gzip, deflate, br',
    'DNT': '1',
    'Connection': 'keep-alive',
    'Upgrade-Insecure-Requests': '1',
    'Sec-Fetch-Dest': 'document',
    'Sec-Fetch-Mode': 'navigate',
    'Sec-Fetch-Site': 'none',
    'Sec-Fetch-User': '?1',
    'Sec-Ch-Ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
    'Sec-Ch-Ua-Mobile': '?0',
    'Sec-Ch-Ua-Platform': '"Windows"',
    'Cache-Control': 'max-age=0'
}

هدرهای Sec-Ch-Ua-* از Chrome 89 معرفی شده‌اند و بخشی از Client Hints API هستند. عدم وجود آن‌ها هنگام استفاده از User-Agent مدرن نشانه‌ای واضح از ربات است.

ترتیب هدرها مهم است

در HTTP/2 ترتیب هدرها برای هر مرورگر ثابت است. Python requests و دیگر کلاینت‌های استاندارد هدرها را به ترتیب الفبایی ارسال می‌کنند که با رفتار مرورگرها متفاوت است. از کتابخانه‌هایی با پشتیبانی از ترتیب سفارشی هدرها استفاده کنید.

نکته: از DevTools مرورگر (زبان شبکه → کلیک راست روی درخواست → کپی → کپی به عنوان cURL) برای دریافت کپی دقیق هدرهای مرورگر واقعی استفاده کنید. سپس آن‌ها را برای کد خود تنظیم کنید.

تولید دینامیک User-Agent

استفاده از یکسان User-Agent برای تمام درخواست‌ها ریسک تشخیص را افزایش می‌دهد. یک مجموعه از User-Agent‌های به‌روز ایجاد کنید و آن‌ها را بچرخانید.

import random

# مجموعه‌ای از User-Agent‌های به‌روز (دسامبر 2024)
USER_AGENTS = [
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Safari/605.1.15',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
]

def get_random_headers():
    ua = random.choice(USER_AGENTS)
    
    # تنظیم سایر هدرها بر اساس UA انتخاب شده
    if 'Chrome' in ua:
        return {
            'User-Agent': ua,
            'Sec-Ch-Ua': '"Not_A Brand";v="8", "Chromium";v="120"',
            # ... سایر هدرهای Chrome
        }
    elif 'Firefox' in ua:
        return {
            'User-Agent': ua,
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
            # ... هدرهای Firefox
        }
    # ... پردازش سایر مرورگرها

استفاده از مرورگرهای headless

زمانی که Cloudflare از چالش JavaScript یا تشخیص پیشرفته استفاده می‌کند، تنها راه مطمئن برای دور زدن — مرورگر واقعی است. مرورگرهای headless به طور خودکار JavaScript، کوکی‌ها را پردازش کرده و یک fingerprint کاملاً معتبر ایجاد می‌کنند.

Playwright با پچ‌های anti-detect

Playwright — یک جایگزین مدرن برای Selenium با عملکرد بهتر است. با این حال، Playwright استاندارد به راحتی از طریق navigator.webdriver و دیگر نشانه‌ها شناسایی می‌شود. از playwright-stealth برای پنهان‌سازی استفاده کنید.

from playwright.sync_api import sync_playwright
from playwright_stealth import stealth_sync

def bypass_cloudflare(url, proxy):
    with sync_playwright() as p:
        browser = p.chromium.launch(
            headless=True,
            proxy={
                "server": f"http://{proxy['host']}:{proxy['port']}",
                "username": proxy['username'],
                "password": proxy['password']
            },
            args=[
                '--disable-blink-features=AutomationControlled',
                '--disable-dev-shm-usage',
                '--no-sandbox'
            ]
        )
        
        context = browser.new_context(
            viewport={'width': 1920, 'height': 1080},
            user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            locale='en-US',
            timezone_id='America/New_York'
        )
        
        page = context.new_page()
        stealth_sync(page)  # اعمال پچ‌های anti-detect
        
        # رفتن به صفحه
        page.goto(url, wait_until='networkidle', timeout=30000)
        
        # انتظار برای عبور از چالش Cloudflare (معمولاً 5-10 ثانیه)
        page.wait_for_timeout(8000)
        
        # بررسی موفقیت در دور زدن
        if 'Just a moment' in page.content():
            print('چالش Cloudflare رد نشده است')
            return None
        
        # استخراج کوکی‌ها برای استفاده بعدی
        cookies = context.cookies()
        html = page.content()
        
        browser.close()
        return {'html': html, 'cookies': cookies}

# استفاده
proxy_config = {
    'host': 'proxy.example.com',
    'port': 8080,
    'username': 'user',
    'password': 'pass'
}

result = bypass_cloudflare('https://example.com', proxy_config)

Puppeteer Extra با پلاگین‌ها

برای اکوسیستم Node.js، بهترین راه‌حل puppeteer-extra با پلاگین puppeteer-extra-plugin-stealth است. این پلاگین بیش از 30 تکنیک مختلف برای پنهان‌سازی اتوماسیون را اعمال می‌کند.

const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');

puppeteer.use(StealthPlugin());

async function bypassCloudflare(url, proxyUrl) {
    const browser = await puppeteer.launch({
        headless: 'new',
        args: [
            `--proxy-server=${proxyUrl}`,
            '--disable-blink-features=AutomationControlled',
            '--window-size=1920,1080'
        ]
    });
    
    const page = await browser.newPage();
    
    // تنظیم viewport و user-agent
    await page.setViewport({ width: 1920, height: 1080 });
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');
    
    // بازنویسی navigator.webdriver
    await page.evaluateOnNewDocument(() => {
        delete Object.getPrototypeOf(navigator).webdriver;
    });
    
    // رفتن به صفحه
    await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 });
    
    // انتظار برای عبور از چالش
    await page.waitForTimeout(8000);
    
    // دریافت محتوا و کوکی‌ها
    const content = await page.content();
    const cookies = await page.cookies();
    
    await browser.close();
    
    return { content, cookies };
}

// مثال استفاده
bypassCloudflare('https://example.com', 'http://user:pass@proxy.example.com:8080')
    .then(result => console.log('موفقیت'))
    .catch(err => console.error(err));

عملکرد: مرورگرهای headless به طور قابل توجهی منابع بیشتری مصرف می‌کنند (200-500 مگابایت RAM برای هر نمونه). برای کارهای با بار بالا، از آن‌ها فقط برای دریافت کوکی‌ها استفاده کنید و سپس به کلاینت‌های HTTP با این کوکی‌ها سوئیچ کنید.

انتخاب نوع پروکسی برای دور زدن Cloudflare

نوع پروکسی تأثیر زیادی بر موفقیت دور زدن دارد. Cloudflare پایگاه‌های داده IP آدرس‌های دیتا سنترها را نگهداری کرده و قوانین بررسی سخت‌تری را به آن‌ها اعمال می‌کند.

نوع پروکسی احتمال دور زدن سرعت هزینه توصیه
دیتا سنتر 30-40% بالا پایین فقط با مرورگرهای headless
مسکونی 85-95% متوسط بالا انتخاب بهینه
موبایل 90-98% متوسط بسیار بالا برای کارهای حساس
ISP (مسکونی ثابت) 80-90% بالا متوسط تعادل قیمت و کیفیت

چرا پروکسی‌های مسکونی مؤثرتر هستند

پروکسی‌های مسکونی از IP آدرس‌های دستگاه‌های واقعی (روترهای خانگی، گوشی‌های هوشمند) استفاده می‌کنند. Cloudflare نمی‌تواند به طور انبوه این IP‌ها را مسدود کند، زیرا این کار کاربران عادی را مسدود می‌کند. آمار نشان می‌دهد که IP‌های مسکونی 15-20 برابر کمتر از دیتا سنترها کپچا دریافت می‌کنند.

هنگام کار با پروکسی‌های مسکونی، موقعیت جغرافیایی بسیار مهم است. اگر وب‌سایت هدف به ایالات متحده متمرکز باشد، استفاده از پروکسی‌های آسیایی احتمال مشکوک بودن را افزایش می‌دهد. ارائه‌دهندگانی با جغرافیای وسیع و امکان هدف‌گذاری بر اساس شهرها را انتخاب کنید.

پروکسی‌های موبایل برای حداکثر قابلیت اطمینان

پروکسی‌های موبایل از IP آدرس‌های اپراتورهای موبایل (4G/5G) استفاده می‌کنند. ویژگی شبکه‌های موبایل — تغییر دینامیک IP از طریق حالت پرواز است که تعداد نامحدودی از IP آدرس‌های تمیز را فراهم می‌کند. احتمال مسدود شدن IP موبایل نزدیک به صفر است.

# مثال چرخش IP موبایل از طریق API
import requests
import time

def rotate_mobile_ip(proxy_api_url):
    """تغییر IP پروکسی موبایل"""
    response = requests.get(f"{proxy_api_url}/rotate")
    if response.status_code == 200:
        print("IP با موفقیت تغییر کرد")
        time.sleep(5)  # انتظار برای اعمال تغییرات
        return True
    return False

# استفاده با پروکسی موبایل
mobile_proxy = "http://user:pass@mobile.proxy.com:8080"

for i in range(10):
    # اجرای درخواست
    response = requests.get(
        'https://example.com',
        proxies={'http': mobile_proxy, 'https': mobile_proxy}
    )
    
    # چرخش IP بعد از هر درخواست
    rotate_mobile_ip('https://api.proxy.com/mobile')

مدیریت کوکی‌ها و نشست‌ها

پس از عبور موفق از چالش Cloudflare، سرور کوکی‌هایی (cf_clearance، __cfduid و دیگران) را تنظیم می‌کند که مشروعیت مشتری را تأیید می‌کنند. مدیریت صحیح این کوکی‌ها به جلوگیری از بررسی‌های مجدد کمک می‌کند.

استخراج و استفاده مجدد از cf_clearance

کوکی cf_clearance معمولاً 30-60 دقیقه معتبر است. پس از دریافت از طریق مرورگر headless، می‌توان از آن در درخواست‌های HTTP عادی استفاده کرد.

import requests
import pickle
from datetime import datetime, timedelta

class CloudflareCookieManager:
    def __init__(self, cookie_file='cf_cookies.pkl'):
        self.cookie_file = cookie_file
        self.cookies = self.load_cookies()
    
    def load_cookies(self):
        """بارگذاری کوکی‌های ذخیره شده"""
        try:
            with open(self.cookie_file, 'rb') as f:
                data = pickle.load(f)
                # بررسی تاریخ انقضا
                if data['expires'] > datetime.now():
                    return data['cookies']
        except FileNotFoundError:
            pass
        return None
    
    def save_cookies(self, cookies, ttl_minutes=30):
        """ذخیره کوکی‌ها با TTL"""
        data = {
            'cookies': cookies,
            'expires': datetime.now() + timedelta(minutes=ttl_minutes)
        }
        with open(self.cookie_file, 'wb') as f:
            pickle.dump(data, f)
    
    def get_cf_clearance(self, url, proxy):
        """دریافت cf_clearance از طریق مرورگر"""
        if self.cookies:
            return self.cookies
        
        # اینجا کد اجرای مرورگر (از بخش قبلی)
        # ...
        browser_cookies = bypass_cloudflare(url, proxy)['cookies']
        
        # تبدیل به فرمت requests
        cookies_dict = {c['name']: c['value'] for c in browser_cookies}
        self.save_cookies(cookies_dict)
        self.cookies = cookies_dict
        
        return cookies_dict
    
    def make_request(self, url, proxy):
        """درخواست با مدیریت خودکار کوکی‌ها"""
        cookies = self.get_cf_clearance(url, proxy)
        
        response = requests.get(
            url,
            cookies=cookies,
            proxies={'http': proxy, 'https': proxy},
            headers=get_random_headers()
        )
        
        # اگر دوباره چالش دریافت کردیم — کوکی‌ها را به‌روزرسانی می‌کنیم
        if response.status_code == 403 or 'cf-browser-verification' in response.text:
            print("کوکی‌ها منقضی شده‌اند، دریافت کوکی‌های جدید...")
            self.cookies = None
            return self.make_request(url, proxy)
        
        return response

# استفاده
manager = CloudflareCookieManager()
response = manager.make_request(
    'https://example.com/api/data',
    'http://user:pass@proxy.example.com:8080'
)

پیوند کوکی‌ها به IP آدرس

Cloudflare cf_clearance را به IP آدرسی که چالش را گذرانده است پیوند می‌زند. استفاده از این کوکی با IP دیگر منجر به مسدود شدن خواهد شد. هنگام کار با پروکسی‌های چرخشی، باید مجموعه‌ای جداگانه از کوکی‌ها را برای هر IP ذخیره کنید.

import hashlib

class IPBoundCookieManager:
    def __init__(self):
        self.cookies_by_ip = {}
    
    def get_ip_hash(self, proxy_url):
        """ایجاد هش برای شناسایی پروکسی"""
        return hashlib.md5(proxy_url.encode()).hexdigest()
    
    def get_cookies_for_proxy(self, proxy_url, target_url):
        """دریافت کوکی‌ها برای پروکسی خاص"""
        ip_hash = self.get_ip_hash(proxy_url)
        
        if ip_hash in self.cookies_by_ip:
            cookies_data = self.cookies_by_ip[ip_hash]
            if cookies_data['expires'] > datetime.now():
                return cookies_data['cookies']
        
        # دریافت کوکی‌های جدید از طریق مرورگر
        new_cookies = self.fetch_cookies_with_browser(target_url, proxy_url)
        
        self.cookies_by_ip[ip_hash] = {
            'cookies': new_cookies,
            'expires': datetime.now() + timedelta(minutes=30)
        }
        
        return new_cookies

چرخش پروکسی و کنترل نرخ درخواست‌ها

حتی با تکنولوژی صحیح، نرخ درخواست‌های بسیار بالا از یک IP، نرخ محدودیت را فعال می‌کند. Cloudflare الگوهای ترافیک را تحلیل کرده و فعالیت‌های غیرعادی را شناسایی می‌کند.

استراتژی‌های چرخش پروکسی

سه رویکرد اصلی برای چرخش وجود دارد: round-robin (متوالی)، random (تصادفی) و sticky sessions (پیوند به نشست). برای دور زدن Cloudflare، استراتژی sticky sessions با محدودیت درخواست‌ها بر روی IP بهینه است.

import time
import random
from collections import defaultdict
from datetime import datetime, timedelta

class SmartProxyRotator:
    def __init__(self, proxy_list, max_requests_per_ip=20, cooldown_minutes=10):
        self.proxy_list = proxy_list
        self.max_requests_per_ip = max_requests_per_ip
        self.cooldown_minutes = cooldown_minutes
        
        # شمارنده‌های استفاده
        self.usage_count = defaultdict(int)
        self.last_used = {}
        self.cooldown_until = {}
    
    def get_proxy(self):
        """دریافت پروکسی بعدی در دسترس"""
        available_proxies = []
        
        for proxy in self.proxy_list:
            # بررسی cooldown
            if proxy in self.cooldown_until:
                if datetime.now() < self.cooldown_until[proxy]:
                    continue
                else:
                    # بازنشانی شمارنده پس از cooldown
                    self.usage_count[proxy] = 0
                    del self.cooldown_until[proxy]
            
            # بررسی محدودیت درخواست‌ها
            if self.usage_count[proxy] < self.max_requests_per_ip:
                available_proxies.append(proxy)
        
        if not available_proxies:
            # اگر همه پروکسی‌ها در cooldown هستند — منتظر بمانید
            wait_time = min(
                (self.cooldown_until[p] - datetime.now()).total_seconds()
                for p in self.cooldown_until
            )
            print(f"همه پروکسی‌ها در cooldown هستند. انتظار {wait_time:.0f} ثانیه...")
            time.sleep(wait_time + 1)
            return self.get_proxy()
        
        # انتخاب پروکسی با کمترین استفاده
        proxy = min(available_proxies, key=lambda p: self.usage_count[p])
        
        self.usage_count[proxy] += 1
        self.last_used[proxy] = datetime.now()
        
        # تنظیم cooldown در صورت رسیدن به حد
        if self.usage_count[proxy] >= self.max_requests_per_ip:
            self.cooldown_until[proxy] = datetime.now() + timedelta(
                minutes=self.cooldown_minutes
            )
            print(f"پروکسی {proxy} به حد خود رسید. Cooldown {self.cooldown_minutes} دقیقه.")
        
        return proxy
    
    def add_delay(self):
        """تاخیر تصادفی بین درخواست‌ها (شبیه‌سازی انسان)"""
        delay = random.uniform(2, 5)  # 2-5 ثانیه
        time.sleep(delay)

# استفاده
proxy_pool = [
    'http://user:pass@proxy1.example.com:8080',
    'http://user:pass@proxy2.example.com:8080',
    'http://user:pass@proxy3.example.com:8080',
    # ... تا 50-100 پروکسی برای عملکرد پایدار
]

rotator = SmartProxyRotator(
    proxy_pool,
    max_requests_per_ip=15,  # مقدار محافظه‌کارانه
    cooldown_minutes=15
)

# اجرای درخواست‌ها
for i in range(1000):
    proxy = rotator.get_proxy()
    
    response = requests.get(
        'https://example.com/page',
        proxies={'http': proxy, 'https': proxy},
        headers=get_random_headers()
    )
    
    print(f"درخواست {i+1}: {response.status_code}")
    rotator.add_delay()

محدودیت نرخ تطبیقی

رویکرد پیشرفته‌تر — تطبیق دینامیک نرخ درخواست‌ها بر اساس پاسخ‌های سرور است. اگر خطاهای 429 یا کپچا شروع به ظاهر شدن کنند، به طور خودکار سرعت را کاهش می‌دهیم.

class AdaptiveRateLimiter:
    def __init__(self, initial_delay=3.0):
        self.delay = initial_delay
        self.min_delay = 1.0
        self.max_delay = 30.0
        self.success_streak = 0
        self.failure_streak = 0
    
    def on_success(self):
        """درخواست موفق — می‌توانیم سرعت را افزایش دهیم"""
        self.success_streak += 1
        self.failure_streak = 0
        
        if self.success_streak >= 10:
            # کاهش تأخیر به 10%
            self.delay = max(self.min_delay, self.delay * 0.9)
            self.success_streak = 0
    
    def on_failure(self, status_code):
        """خطا — سرعت را کاهش می‌دهیم"""
        self.failure_streak += 1
        self.success_streak = 0
        
        if status_code == 429:  # محدودیت نرخ
            # کاهش تهاجمی
            self.delay = min(self.max_delay, self.delay * 2.0)
        elif status_code == 403:  # احتمال مسدود شدن
            self.delay = min(self.max_delay, self.delay * 1.5)
        
        print(f"تأخیر به {self.delay:.2f}s افزایش یافت")
    
    def wait(self):
        """انتظار قبل از درخواست بعدی"""
        # افزودن تصادفی ±20%
        actual_delay = self.delay * random.uniform(0.8, 1.2)
        time.sleep(actual_delay)

ابزارها و کتابخانه‌های آماده برای دور زدن

توسعه یک راه‌حل سفارشی از ابتدا زمان و تخصص می‌طلبد. ابزارهای آماده‌ای وجود دارند که فرآیند دور زدن Cloudflare را خودکار می‌کنند.

cloudscraper (Python)

کتابخانه cloudscraper — یک لایه بالایی بر روی requests است که به طور خودکار چالش‌های JavaScript را حل می‌کند. با حفاظت‌های پایه کار می‌کند، اما ممکن است نتواند با بررسی‌های پیشرفته کنار بیاید.

import cloudscraper

# ایجاد scraper با پشتیبانی از پروکسی
scraper = cloudscraper.create_scraper(
    browser={
        'browser': 'chrome',
        'platform': 'windows',
        'desktop': True
    }
)

# تنظیم پروکسی
proxies = {
    'http': 'http://user:pass@proxy.example.com:8080',
    'https': 'http://user:pass@proxy.example.com:8080'
}

# اجرای درخواست
response = scraper.get('https://example.com', proxies=proxies)

if response.status_code == 200:
    print("دور زدن موفق")
    print(response.text)
else:
    print(f"خطا: {response.status_code}")

FlareSolverr (عمومی)

FlareSolverr — یک پروکسی سرور است که مرورگر headless را برای حل چالش‌های Cloudflare اجرا می‌کند. از طریق HTTP API کار می‌کند و از هر زبان برنامه‌نویسی پشتیبانی می‌کند.

# اجرای FlareSolverr از طریق Docker
docker run -d \
  --name=flaresolverr \
  -p 8191:8191 \
  -e LOG_LEVEL=info \
  ghcr.io/flaresolverr/flaresolverr:latest

# استفاده از Python
import requests

def solve_cloudflare(url, proxy=None):
    flaresolverr_url = "http://localhost:8191/v1"
    
    payload = {
        "cmd": "request.get",
        "url": url,
        "maxTimeout": 60000
    }
    
    if proxy:
        payload["proxy"] = {
            "url": proxy
        }
    
    response = requests.post(flaresolverr_url, json=payload)
    result = response.json()
    
    if result['status'] == 'ok':
        return {
            'html': result['solution']['response'],
            'cookies': result['solution']['cookies'],
            'user_agent': result['solution']['userAgent']
        }
    else:
        raise Exception(f"خطای FlareSolverr: {result['message']}")

# مثال استفاده
result = solve_cloudflare(
    'https://example.com',
    proxy='http://user:pass@proxy.example.com:8080'
)

print(result['html'])

undetected-chromedriver

نسخه پچ شده Selenium ChromeDriver که به طور خودکار تکنیک‌های anti-detect متعددی را اعمال می‌کند. استفاده از آن آسان‌تر از Playwright است، اما کمتر انعطاف‌پذیر است.

import undetected_chromedriver as uc
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

def bypass_with_uc(url, proxy):
    options = uc.ChromeOptions()
    options.add_argument(f'--proxy-server={proxy}')
    options.add_argument('--disable-blink-features=AutomationControlled')
    
    driver = uc.Chrome(options=options, version_main=120)
    
    try:
        driver.get(url)
        
        # انتظار برای ناپدید شدن چالش Cloudflare
        WebDriverWait(driver, 20).until_not(
            EC.presence_of_element_located((By.ID, "cf-spinner-please-wait"))
        )
        
        # انتظار اضافی برای اطمینان
        time.sleep(3)
        
        # دریافت نتیجه
        html = driver.page_source
        cookies = driver.get_cookies()
        
        return {'html': html, 'cookies': cookies}
    
    finally:
        driver.quit()

# استفاده
result = bypass_with_uc(
    'https://example.com',
    'http://user:pass@proxy.example.com:8080'
)

رویکرد ترکیبی: استراتژی بهینه — استفاده از مرورگر headless فقط برای دریافت اولیه کوکی‌ها، سپس سوئیچ به کلاینت‌های HTTP (tls-client، cloudscraper) با این کوکی‌ها. این تعادل بین قابلیت اطمینان و عملکرد را فراهم می‌کند.

نتیجه‌گیری

دور زدن Cloudflare هنگام کار از طریق پروکسی نیاز به یک رویکرد جامع دارد: TLS fingerprint صحیح، هدرهای HTTP معتبر، پروکسی‌های با کیفیت و مدیریت هوشمند نشست‌ها. توصیه‌های کلیدی:

  • از پروکسی‌های مسکونی یا پروکسی‌های موبایل به جای دیتا سنترها استفاده کنید
  • از کتابخانه‌هایی با TLS fingerprint صحیح (tls-client، curl-impersonate) استفاده کنید
  • برای موارد پیچیده از مرورگرهای headless با پچ‌های anti-detect استفاده کنید
  • کوکی‌های cf_clearance را ذخیره و دوباره استفاده کنید
  • پروکسی‌ها را با توجه به محدودیت نرخ بچرخانید (بیش از 15-20 درخواست در IP نباشد)
  • بین درخواست‌ها تأخیرهای تصادفی (2-5 ثانیه) اضافه کنید

حفاظت Cloudflare به طور مداوم در حال تکامل است، بنابراین مهم است که به طور منظم ابزارها را به‌روزرسانی کرده و استراتژی‌ها را تطبیق دهید. تغییرات در تکنیک‌های fingerprinting را رصد کرده و راه‌حل‌ها را بر روی نسخه‌های به‌روز حفاظت آزمایش کنید.

برای عملکرد پایدار، توصیه می‌شود از خدمات پروکسی حرفه‌ای با مجموعه وسیع IP و چرخش خودکار استفاده کنید.

```