الحل الأكثر ثباتاً لاختبارات CAPTCHA في المتصفح بدون رأس هو حلّها من جهة الخادم عبر API بدل محاولة منع ظهورها. الأتمتة بدون واجهة رسومية تستدعي تحديات أكثر من المتصفح العادي، لأن المواقع تقرأ بصمات JavaScript وتضبط درجة ثقة أقل لأي جلسة تبدو آلية.
يقوم هذا الدليل على ثلاث طبقات متكاملة تعمل مع Chrome وFirefox وWebKit في وضع بدون رأس:
- حلّ التحدي من جهة الخادم عبر الـ API حين يظهر.
- تقليل الإشارات التي تجعل الجلسة تبدو آلية.
- التعامل مع صفحات Cloudflare Challenge كحالة خاصة تتطلب أكثر من رمز.
لماذا تظهر اختبارات CAPTCHA أكثر في المتصفحات بدون رأس؟
المتصفح في وضع بدون رأس يترك آثاراً تقنية يسهل رصدها. أبرز الإشارات التي تفحصها أنظمة مكافحة الروبوتات:
navigator.webdriver: مضبوط علىtrueفي وضع بدون رأس.- أبعاد النافذة: مقاس 800x600 الافتراضي شائع في الوضع بدون رأس ونادر على أجهزة المستخدمين.
- عارض WebGL: يعيد القيمة "SwiftShader" بدل بطاقة رسومية حقيقية.
- Chrome DevTools Protocol: منفذ CDP مفتوح يكشف التحكم البرمجي.
- الإضافات المفقودة: غياب عارض PDF أو Flash وما شابه.
- Permissions API: استجابات مختلفة عن المتصفح العادي.
- سلسلة User-Agent: تحتوي على النص الفرعي "HeadlessChrome".
عندما تجتمع هذه الإشارات معاً، تمنح أنظمة مثل reCAPTCHA وCloudflare وDataDome الجلسة درجة ثقة منخفضة وتعرض اختبار CAPTCHA. المهم أن تفهم أن أياً من هذه الإشارات وحده لا يكفي عادةً؛ التراكم هو ما يرفع احتمال التحدي، ولهذا تعمل الحلول التالية على مسارين متوازيين: تقليل الإشارات المكشوفة، وحلّ ما يظهر منها على أي حال.
الحل الأول: حلّ اختبارات CAPTCHA من جهة الخادم عبر الـ API
بدلاً من مطاردة كل إشارة بصمة على حدة، تعامل مع التحدي حين يظهر. تعمل CaptchaAI مع أي متصفح بدون رأس لأنها تحلّ اختبار CAPTCHA من جهة الخادم: يرسل السكربت مفتاح الموقع وعنوان الصفحة، ويستقبل الرمز الجاهز للحقن. تدعم الخدمة reCAPTCHA v2 وv3 وCloudflare Turnstile وChallenge وGeeTest v3 وصور OCR والشبكات، وهي الأنواع التي تصادفها غالباً في الأتمتة بدون رأس.
Selenium (Python)
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import requests
import time
API_KEY = "YOUR_API_KEY"
options = Options()
options.add_argument("--headless=new")
options.add_argument("--disable-blink-features=AutomationControlled")
driver = webdriver.Chrome(options=options)
driver.get("https://example.com/login")
# Check for CAPTCHA
recaptcha = driver.find_elements("class name", "g-recaptcha")
if recaptcha:
site_key = recaptcha[0].get_attribute("data-sitekey")
# Solve via CaptchaAI
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": API_KEY, "method": "userrecaptcha",
"googlekey": site_key, "pageurl": driver.current_url
})
task_id = resp.text.split("|")[1]
while True:
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": task_id
})
if result.text == "CAPCHA_NOT_READY": continue
token = result.text.split("|")[1]
break
# Inject token
driver.execute_script(
f"document.getElementById('g-recaptcha-response').innerHTML = '{token}';"
)
driver.find_element("css selector", "form").submit()
تسير الدالة في خمس خطوات واضحة:
- افحص وجود عنصر
g-recaptchaواقرأ منهdata-sitekey. - أرسل المهمة إلى
in.phpمع الطريقةuserrecaptcha. - استطلع النتيجة دورياً من
res.phpحتى تصل الاستجابة. - احقن الرمز داخل حقل
g-recaptcha-response. - أرسل النموذج لإتمام العملية.
Puppeteer (Node.js)
const puppeteer = require("puppeteer");
const axios = require("axios");
const API_KEY = "YOUR_API_KEY";
const browser = await puppeteer.launch({ headless: "new" });
const page = await browser.newPage();
await page.goto("https://example.com/login");
// Check for CAPTCHA
const siteKey = await page
.$eval(".g-recaptcha", (el) => el.getAttribute("data-sitekey"))
.catch(() => null);
if (siteKey) {
const submit = await axios.get("https://ocr.captchaai.com/in.php", {
params: {
key: API_KEY,
method: "userrecaptcha",
googlekey: siteKey,
pageurl: page.url(),
},
});
const taskId = submit.data.split("|")[1];
let token;
while (true) {
await new Promise((r) => setTimeout(r, 5000));
const result = await axios.get("https://ocr.captchaai.com/res.php", {
params: { key: API_KEY, action: "get", id: taskId },
});
if (result.data === "CAPCHA_NOT_READY") continue;
token = result.data.split("|")[1];
break;
}
await page.evaluate((t) => {
document.getElementById("g-recaptcha-response").innerHTML = t;
}, token);
await page.click('button[type="submit"]');
}
النمط ذاته يتكرر في Puppeteer عبر خطوات متطابقة:
- قراءة
data-sitekeyمن عنصر.g-recaptcha. - إرسال الطلب ثم انتظار النتيجة عبر الاستطلاع الدوري.
- حقن الرمز والضغط على زر الإرسال.
ولأن الحل يحدث من جهة الخادم، لا يهمّ إن كان المتصفح يعمل بواجهة رسومية أو بدونها.
الحل الثاني: تقليل عدد مرات ظهور اختبارات CAPTCHA
يمكنك دائماً حلّ التحدي عبر الـ API، لكن كلما قلّ عدد مرات ظهوره وفّرت وقت التنفيذ ورصيد الحساب. الهدف هنا ليس إخفاء الأتمتة، بل جعل الجلسة أقرب إلى متصفح واقعي حتى لا تُصنّف كإشارة مشبوهة تلقائياً.
تعطيل إشارة navigator.webdriver
أوّل ما تفحصه أغلب الأنظمة هو قيمة navigator.webdriver. ضبطها بحيث لا تكشف الأتمتة يزيل أوضح إشارة على الجلسة الآلية:
# Selenium
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
// Puppeteer
await page.evaluateOnNewDocument(() => {
Object.defineProperty(navigator, "webdriver", { get: () => false });
});
ضبط أبعاد نافذة واقعية
مقاس 800x600 الافتراضي في الوضع بدون رأس نادر على أجهزة المستخدمين الفعليين، فاضبط أبعاداً شائعة مثل 1920×1080:
# Selenium
driver.set_window_size(1920, 1080)
// Puppeteer
await page.setViewport({ width: 1920, height: 1080 });
إضافات تقليل بصمة الأتمتة
توجد إضافات جاهزة توحّد سلوك المتصفح مع نظيره الواقعي وتغلق فجوات بصمة معروفة. في Puppeteer تُستخدم إضافة puppeteer-extra-plugin-stealth، وفي Selenium يقوم undetected-chromedriver بدور مشابه:
# Puppeteer
npm install puppeteer-extra puppeteer-extra-plugin-stealth
const puppeteer = require("puppeteer-extra");
const StealthPlugin = require("puppeteer-extra-plugin-stealth");
puppeteer.use(StealthPlugin());
# Selenium
pip install undetected-chromedriver
import undetected_chromedriver as uc
driver = uc.Chrome(headless=True)
هذه الخطوة تقلّل التكرار لكنها لا تلغيه؛ لذا تبقى الطبقة الأولى (الحل عبر الـ API) هي شبكة الأمان التي تُبقي التشغيل الآلي مستمراً عند ظهور أي تحدٍّ.
الحل الثالث: التعامل مع Cloudflare Challenge
صفحات تحدي Cloudflare تتطلب أكثر من مجرد رمز؛ فهي تحتاج إلى ملف تعريف الارتباط cf_clearance وسلسلة User-Agent المطابقة. تعيد CaptchaAI الاثنين معاً لتستخدمهما في الطلبات اللاحقة داخل الجلسة نفسها:
# CaptchaAI handles full Cloudflare challenges
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": API_KEY,
"method": "cloudflare_challenge",
"pageurl": "https://example.com",
"proxy": "http://user:pass@proxy:port",
"proxytype": "HTTP"
})
task_id = resp.text.split("|")[1]
# Result includes cf_clearance cookie and user_agent
# Use both to make subsequent requests
انتبه إلى أن cf_clearance مرتبط بعنوان IP وبالـ User-Agent؛ إذا غيّرت الخادم الوسيط أو سلسلة المتصفح بين الطلبات، سيبطل ملف التعريف وتظهر صفحة التحدي من جديد.
مشكلات شائعة بحسب المتصفح
لكل بيئة تشغيل نقطة ضعف متكررة، وأبرزها مع الإصلاح المباشر:
- Headless Chrome: قيمة
navigator.webdriver = true— استخدم علامة--disable-blink-features. - Puppeteer: غياب إضافات المتصفح — استخدم
puppeteer-extra-plugin-stealth. - Selenium: مبدّل
enable-automation— عطّله عبرexcludeSwitches: ["enable-automation"]. - Playwright: بصمة WebKit — استخدم قناة Chromium مع تصحيحات التخفي.
- جميع البيئات: مقاس ثابت لنافذة العرض — اضبطه على 1920×1080 أو نوّعه عشوائياً.
سيناريو من السوق: مراقبة الأسعار على خادم CI
لنفترض فريق تسعير في الخليج يشغّل مهمة مراقبة يومية لأسعار منتجات على موقع تجزئة إقليمي. المهمة تعمل بـ Headless Chrome على خادم Linux داخل خط CI بلا واجهة رسومية، فتبدأ صفحات المنتجات بعرض تحدي Cloudflare بعد عشرات الطلبات. الحل العملي هنا يقوم على طبقتين:
- تقليل التكرار: ضبط أبعاد نافذة واقعية وتعطيل إشارة
navigator.webdriverحتى لا تُصنّف الجلسة كآلية من أول طلب. - الحل عند الظهور: توجيه أي تحدٍّ يبقى إلى CaptchaAI لحلّه من جهة الخادم واستعادة
cf_clearanceومتابعة الزحف.
النقطة الحاسمة: لا تعتمد على طبقة واحدة. تقليل البصمة وحده يترك ثغرات على نطاق واسع، والحل عبر الـ API وحده يستهلك خيوطاً أكثر من اللازم. الجمع بينهما هو ما يمنح تشغيلاً مستقراً.
أما التكلفة، فتعتمد CaptchaAI على تسعير قائم على عدد الخيوط المتزامنة (Threads) لا على عدد عمليات الحل، وكل خطة تتضمن عدداً غير محدود من عمليات الحل خلال الشهر:
- خطة BASIC بسعر 15 دولاراً شهرياً تتيح 5 خيوط متزامنة، وهي كافية لمهمة مراقبة صغيرة تعالج طلباتها بالتوازي.
- عند التوسّع ترفع الخطط الأعلى عدد الخيوط لا سعر الحل الواحد، فتبقى التكلفة الشهرية قابلة للتوقّع دون رسوم لكل اختبار.
الأسئلة الشائعة
هل أحتاج أصلاً إلى متصفح بدون رأس لحلّ CAPTCHA؟
ليس دائماً. إذا كان هدفك حلّ reCAPTCHA أو Turnstile فقط، يكفي إرسال مفتاح الموقع وعنوان الصفحة إلى الـ API دون تشغيل متصفح كامل. تحتاج المتصفح بدون رأس حين تتطلب المهمة تفاعلاً مع الصفحة نفسها، مثل تعبئة نموذج أو حقن الرمز داخل الـ DOM قبل الإرسال.
أي متصفح يستدعي أكثر اختبارات CAPTCHA؟
Headless Chrome بإعداداته الافتراضية هو الأكثر عرضة للكشف بسبب إشارات مثل navigator.webdriver وسلسلة "HeadlessChrome". يقلّل ضبط الأبعاد وإضافات التخفي هذا التكرار، لكن الأنظمة المتقدمة مثل Cloudflare وPerimeterX تبقى قادرة على الرصد عبر بصمات أدق، لذا يظل الحل عبر الـ API الطبقة الأضمن.
هل يغني cf_clearance عن إعادة حلّ التحدي في كل طلب؟
نعم ضمن الجلسة نفسها. ما دمت تحافظ على عنوان IP وسلسلة User-Agent اللذين صدر بهما ملف التعريف، يمكنك إرسال عدة طلبات بالرمز ذاته حتى انتهاء صلاحيته. تغيير الخادم الوسيط أو المتصفح يبطله ويفرض حلّاً جديداً.
هل تلغي إضافات التخفي الحاجة إلى خدمة حل؟
لا. إضافات مثل puppeteer-extra-plugin-stealth تقلّل عدد مرات ظهور التحدي لكنها لا تمنعه على نطاق واسع. الجمع بين تقليل البصمة كطبقة أولى والحل من جهة الخادم كطبقة ثانية هو ما يمنح تشغيلاً مستقراً وقابلاً للتكرار.