استكشاف الأخطاء

حلقة Cloudflare Challenge: لماذا تستمر التحديات في التكرار

إذا نجح طلبك الأول بعد حل تحدي Cloudflare ثم عاد التحدي في الطلب الذي يليه، فالخلل ليس في الحل نفسه بل في جلستك. ملف cf_clearance الذي حصلت عليه ليس مفتاحاً يفتح كل باب، بل جواز مرور مربوط بسياق محدّد: عنوان IP ووكيل المستخدم والمجال. حالما يتغيّر أحد هذه العناصر بين لحظة الحل ولحظة التصفح، يعتبره Cloudflare جلسة غريبة ويعرض التحدي من جديد — وهكذا تدور الحلقة. في السطور التالية نفكّك الأسباب الخمسة الأكثر تكراراً، ونعطي لكل سبب إصلاحاً عملياً تنسخه مباشرة.

جدول تشخيص سريع: من العرَض إلى الإصلاح

قبل الدخول في التفاصيل، إليك خريطة تنقلك من العرَض الذي تراه إلى السبب الأرجح وإلى الإصلاح المناسب. ابدأ من الصف الأقرب إلى حالتك ثم انتقل إلى قسمه المفصّل أسفل الصفحة.

ما تلاحظه السبب الأرجح الإصلاح المباشر
التحدي يعود من الطلب الثاني مباشرة اختلاف وكيل المستخدم وحِّد User-Agent بين الحل والتصفح
يعمل محلياً ثم يفشل على الخادم تغيُّر عنوان IP ثبِّت الجلسة على وكيل ثابت
الملف مرفوض رغم تطابق IP ووكيل المستخدم المجال مضبوط على قيمة خطأ اسبق اسم المجال بنقطة
يعمل دقائق ثم يعود فجأة انتهاء صلاحية الملف أعِد الحل قبل انقضاء المهلة
كل العناصر متطابقة والتحدي مستمر بصمة TLS غير متصفّحية استعمل curl_cffi أو tls-client

كيف يربط Cloudflare ملف cf_clearance بجلستك

عندما يحل CaptchaAI تحدي Cloudflare Challenge، يعيد لك ملف cf_clearance جاهزاً. المهم أن تدرك أن هذا الملف مقيّد لحظة إصداره بثلاثة عناصر لا تقبل التغيير:

  1. عنوان IP للخادم الوسيط الذي جرى الحل من خلاله.
  2. وكيل المستخدم (User-Agent) المُرسَل أثناء الحل.
  3. المجال (domain) الخاص بالموقع المستهدف.

اجعل هذه الأسئلة الثلاثة قائمة تحقق سريعة قبل كل تشغيل:

  • هل يخرج الحل والتصفح من عنوان IP واحد بلا تبديل؟
  • هل وكيل المستخدم واحد حرفاً بحرف في موضع الحل وموضع التصفح؟
  • هل ضُبط الملف على مجال الموقع المستهدف نفسه؟

طالما بقيت الإجابات "نعم"، يمرّرك Cloudflare بلا اعتراض؛ وأول إجابة بـ"لا" هي غالباً مصدر الحلقة.

متى تظهر الحلقة عملياً؟ سيناريو من الميدان

تخيّل فريقاً في القاهرة يبني أداة لمراقبة أسعار موقع حجوزات إقليمي. السكربت يعمل بلا عيب على أجهزة المطوّرين لأن الحل والتصفح يخرجان من الوكيل السكني نفسه. ثم يُنشَر المشروع على خادم سحابي في منطقة فرانكفورت داخل حاوية Docker، فتبدأ الحلقة فوراً: صار الحل يتم عبر الوكيل السكني بينما يخرج التصفح من عنوان IP الخاص بمركز البيانات.

القاعدة المستخلصة: اربط الحل والتصفح بالخادم الوسيط نفسه في كل بيئة تشغيل، سواء كانت جهازك المحلي أو خادماً في أي منطقة سحابية.

السبب الأول: وكيل المستخدم لا يتطابق بين الحل والتصفح

هذا أشيع الأسباب على الإطلاق. وكيل المستخدم الذي ترسله إلى CaptchaAI عند الحل يجب أن يطابق حرفاً بحرف وكيل المستخدم في طلباتك اللاحقة. فرق بسيط — حتى في رقم إصدار Chrome — يكفي وحده لرفض الملف وإعادة التحدي.

import requests

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"

# Step 1: Solve with the SAME User-Agent
solve_data = {
    "key": "YOUR_API_KEY",
    "method": "cloudflare_challenge",
    "pageurl": "https://example.com",
    "proxy": "host:port:user:pass",
    "proxytype": "HTTP",
    "userAgent": USER_AGENT,  # Must match step 2
    "json": 1
}
submit = requests.post("https://ocr.captchaai.com/in.php", data=solve_data).json()

# ... poll for result ...

# Step 2: Use the SAME User-Agent in subsequent requests
session = requests.Session()
session.headers["User-Agent"] = USER_AGENT  # Must match step 1
session.cookies.set("cf_clearance", cf_clearance_value, domain=".example.com")
resp = session.get("https://example.com")

نصيحة عملية: عرّف قيمة وكيل المستخدم في ثابت واحد واستعمله في موضع الحل وموضع التصفح معاً، فلا يتسرب اختلاف خفيّ بينهما.

السبب الثاني: عنوان IP يتغيّر بعد الحل

ملف cf_clearance مربوط بعنوان IP الذي حلّ التحدي تحديداً. أرسِل الطلب اللاحق من عنوان مختلف، وسيُرفض الملف في الحال دون أي تسامح.

PROXY = "host:port:user:pass"

# Solve with this proxy
solve_data = {
    "key": "YOUR_API_KEY",
    "method": "cloudflare_challenge",
    "pageurl": "https://example.com",
    "proxy": PROXY,
    "proxytype": "HTTP",
    "userAgent": USER_AGENT,
    "json": 1
}

# Use the SAME proxy for subsequent requests
session.proxies = {
    "http": f"http://user:pass@host:port",
    "https": f"http://user:pass@host:port"
}

نقطة حاسمة: إن كنت تستخدم وكلاء متناوبين، ثبّت الجلسة على وكيل ثابت (sticky session). عنوان IP يجب أن يظل كما هو تماماً بين الحل والتصفح، وإلا عادت الحلقة من نقطة الصفر.

السبب الثالث: المجال الخاطئ عند ضبط ملف تعريف الارتباط

حتى مع عنوان IP ووكيل مستخدم صحيحين، يتكرر التحدي إذا ضُبط الملف على مجال غير مطابق. أكثر الأخطاء تكراراً في هذا الموضع:

  • ضبط الملف على example.com بلا نقطة بادئة، فلا يشمل النطاقات الفرعية.
  • ضبطه على نطاق فرعي واحد بينما ينتقل التصفح بين عدة نطاقات فرعية.
  • الاكتفاء بحقن cf_clearance وترك بقية الملفات التي يعيدها المزوّد.
# WRONG — setting on wrong domain
session.cookies.set("cf_clearance", value, domain="example.com")

# CORRECT — include the dot prefix for subdomain coverage
session.cookies.set("cf_clearance", value, domain=".example.com")

# Or set all cookies returned by CaptchaAI
for cookie_str in result.get("cookies", "").split(";"):
    if "cf_clearance" in cookie_str:
        name, val = cookie_str.strip().split("=", 1)
        session.cookies.set(name.strip(), val.strip(), domain=".example.com")

عملياً، الأسلم أن تحقن كل الملفات التي يعيدها CaptchaAI بدل انتقاء cf_clearance وحده، فبعض المواقع تطلب ملفات مصاحبة إلى جانبه.

السبب الرابع: انتهت صلاحية cf_clearance

عمر ملف cf_clearance قصير — عادة بين 15 و30 دقيقة، وبعض المواقع تفرض مدداً أقصر. بمجرد انتهاء الصلاحية يعود التحدي، حتى لو ظل كل شيء آخر مطابقاً تماماً. وهي حالة خادعة لأنها تظهر بعد فترة من العمل السليم.

الإصلاح: راقب عمر الملف وأعِد الحل استباقياً قبل بلوغ المهلة، لا بعد أن يظهر التحدي.

import time

last_solve_time = None
COOKIE_TTL = 900  # 15 minutes

def get_cf_clearance():
    global last_solve_time
    if last_solve_time and (time.time() - last_solve_time) < COOKIE_TTL:
        return  # Cookie still valid

    # Solve again
    cf_clearance = solve_cloudflare_challenge()
    session.cookies.set("cf_clearance", cf_clearance, domain=".example.com")
    last_solve_time = time.time()

السبب الخامس: بصمة TLS لا تُشبه متصفحاً

يفحص Cloudflare بصمة TLS للاتصال نفسه. مكتبة requests في Python تترك بصمة مختلفة عن بصمة Chrome، وبعض المواقع ترفض الطلب حتى مع ملف cf_clearance سليم إذا لم تُشبه البصمة متصفحاً حقيقياً. هذا السبب هو الأخفى لأنه لا علاقة له بالملف ولا بالعناصر الثلاثة السابقة.

الإصلاح: استعن بإحدى المكتبتين التاليتين للحصول على بصمة قريبة من المتصفح:

  • curl_cffi — تحاكي بصمة إصدارات Chrome مباشرة عبر وضع impersonate.
  • tls-client — بديل يمنحك تحكماً أدق في تفاصيل مصافحة TLS.
pip install curl_cffi
from curl_cffi import requests as curl_requests

session = curl_requests.Session(impersonate="chrome120")
session.cookies.set("cf_clearance", value, domain=".example.com")
resp = session.get("https://example.com")

شجرة قرار سريعة لتحديد السبب

راجع النقاط من الأعلى إلى الأسفل؛ أول إجابة بـ"لا" هي على الأرجح مصدر الحلقة لديك:

Challenge keeps repeating
    ↓
User-Agent in solve request matches browsing request? → No → Sync User-Agent
    ↓ Yes
Same proxy IP for solve and browse? → No → Pin proxy IP (sticky session)
    ↓ Yes
Cookie set on correct domain (.example.com)? → No → Fix domain
    ↓ Yes
Cookie less than 15 minutes old? → No → Re-solve the challenge
    ↓ Yes
TLS fingerprint matches a browser? → No → Use curl_cffi or tls-client
    ↓ Yes
Site may have additional bot detection → Use headless browser instead

أسئلة شائعة حول حلقة تحدي Cloudflare

هذه أكثر الأسئلة تكراراً من فرق استخراج البيانات وأتمتة الاختبار حين تواجه حلقة التحدي:

لماذا ينجح الطلب الأول ثم يعود التحدي في الطلب الثاني؟

غالباً لأن الطلب الأول خرج من نفس سياق الحل، ثم تبدّل عنصر بينهما — كأن تتناوب الوكلاء أو يعيد إطار العمل بناء الجلسة بوكيل مستخدم افتراضي مختلف. ثبّت العناصر الثلاثة عبر الطلبات كلها.

كيف أعرف أن السبب هو بصمة TLS تحديداً وليس عنصراً آخر؟

إذا تحققت من تطابق وكيل المستخدم وعنوان IP والمجال وصلاحية الملف ومع ذلك يعود التحدي، فبصمة TLS هي المشتبه الأول. جرّب curl_cffi بوضع impersonate؛ فإن توقفت الحلقة عرفت أن البصمة كانت المشكلة.

هل أستطيع مشاركة ملف cf_clearance واحد بين عدة خيوط متوازية؟

لا يُنصح بذلك. كل خيط يخرج عادة من عنوان IP مختلف، فيُرفض الملف عند أول خيط يخالف عنوان الحل. اجعل لكل جلسة وكيلها وملف cf_clearance الخاص بها.

هل يختلف الأمر إذا كنت أتعامل مع Cloudflare Turnstile بدل Challenge؟

نعم في التفاصيل، لكن مبدأ ربط الجلسة بالسياق واحد. Turnstile عادةً تحقق لحظي داخل الصفحة يُستهلك فور نجاحه، بينما cf_clearance ملف مستمر عبر الطلبات؛ ولهذا يكون تطابق عنوان IP ووكيل المستخدم أشد حساسية في حالة Cloudflare Challenge لأن الملف يُعاد استخدامه في كل طلب لاحق.

جرّبت كل ما سبق ولا يزال التحدي يعود، فما التالي؟

على الأرجح يفرض الموقع طبقة كشف إضافية عن الروبوتات تتجاوز ملفاً واحداً. انتقل حينها إلى متصفح مُدار (headless) يحمل بصمة متصفح كاملة، بدل الاكتفاء بمكتبة طلبات بسيطة.

اكسر حلقة التحدي مع CaptchaAI

مع CaptchaAI تحصل على ملف cf_clearance مرتبطاً بالخادم الوسيط ووكيل المستخدم اللذين تحددهما أنت، فلا يبقى مجال لاختلاف السياق ويتوقف تكرار التحدي. ابدأ الآن من captchaai.com.

تذكّر أن نصف المعركة إعداد صحيح من أول طلب: ثبّت الوكيل ووكيل المستخدم، ثم احقن الملف على المجال الصحيح، فتوفّر على نفسك دوامة إعادة الحل.

أدلة ذات صلة

التعليقات غير مفعّلة لهذا المقال.