سكربت الأتمتة يملأ الحقول بشكل صحيح، يضغط زر الإرسال، ثم يعود الردّ برسالة «تعذّر التحقق» دون أن تظهر أي صورة أو مربع اختيار. في أغلب هذه الحالات يكون السبب reCAPTCHA v2 Invisible: اختبار لا يطلب من المستخدم شيئًا، ويعمل لحظة الضغط على الزر، ولا يعرض تحديًا مرئيًا إلا حين يشتبه تحليل المخاطر لدى Google في نمط السلوك. الخلاصة العملية في ثلاث خطوات: اكتشف وجوده من السمة data-size أو من الشارة الصغيرة في زاوية الصفحة، استخرج sitekey وعنوان الصفحة، ثم أرسل المهمة إلى CaptchaAI مع الراية invisible=1 واحقن الرمز الناتج قبل تشغيل رد النداء.
لماذا يمرّ هذا التحقق دون أن تلاحظه
المشكلة الأولى ليست في الحل، بل في التشخيص. النسخة القياسية من reCAPTCHA v2 تترك أثرًا واضحًا: مربع اختيار يعطّل خطوة الإرسال حتى يُنقر. أما النسخة غير المرئية فلا تعطّل شيئًا؛ الصفحة تبدو طبيعية تمامًا، والنموذج يُرسل فعلًا، والخادم هو من يرفض الطلب لأن الحقل g-recaptcha-response وصل فارغًا أو بقيمة منتهية الصلاحية.
هذا يعني أن سجلّات الأتمتة لن تُظهر كلمة CAPTCHA في أي مكان. ما تراه بدلًا منها:
- استجابة 200 مع رسالة خطأ عامة داخل النموذج.
- إعادة توجيه صامتة إلى الصفحة نفسها.
- محاولات إرسال متكررة تفشل جميعها بالطريقة ذاتها.
لذلك يبدأ التعامل الصحيح من فحص مصدر الصفحة قبل كتابة أي منطق لإعادة المحاولة.
أربع علامات تكشف reCAPTCHA v2 Invisible داخل الصفحة
تُنفَّذ الفحوص التالية من وحدة تحكم المتصفح، وتغطي أنماط التركيب الشائعة — من الودجت المعلَن في HTML إلى الاستدعاء البرمجي.
1. اقرأ السمة data-size داخل عنصر الودجت
أسرع الفحوص وأكثرها حسمًا: إذا كانت قيمة data-size تساوي invisible فأنت أمام النسخة غير المرئية مباشرة.
// Browser console
const widgets = document.querySelectorAll('.g-recaptcha');
widgets.forEach((el, i) => {
const size = el.getAttribute('data-size');
const sitekey = el.getAttribute('data-sitekey');
console.log(`Widget ${i}: size=${size}, sitekey=${sitekey}`);
if (size === 'invisible') {
console.log(' → This is Invisible reCAPTCHA');
}
});
2. ابحث عن الشارة grecaptcha-badge
النسخة غير المرئية تعرض شارة صغيرة في زاوية الصفحة، وكثير من المواقع تُخفيها عبر CSS مع بقاء العنصر موجودًا في DOM:
const badge = document.querySelector('.grecaptcha-badge');
if (badge) {
console.log('reCAPTCHA badge found — likely Invisible reCAPTCHA');
console.log('Badge visibility:', getComputedStyle(badge).visibility);
}
وجود العنصر مع visibility: hidden مؤشر قوي على النسخة غير المرئية، لا نفي لها.
3. تتبّع استدعاءات grecaptcha.execute في سكربتات الصفحة
حين تعتمد الصفحة على الاستدعاء البرمجي ولا تحتوي على عنصر .g-recaptcha إطلاقًا، يبقى sitekey قابلًا للاستخراج من نص السكربت نفسه:
// Look for grecaptcha.execute in page scripts
document.querySelectorAll('script:not([src])').forEach(s => {
if (s.textContent.includes('grecaptcha.execute')) {
console.log('Found grecaptcha.execute — Invisible reCAPTCHA');
const match = s.textContent.match(/grecaptcha\.execute\s*\(\s*['"]?([^'",\s)]+)/);
if (match) console.log('Sitekey:', match[1]);
}
});
4. افحص رابط سكربت reCAPTCHA والمعامل render
المعامل render= في رابط التحميل يفرّق بين التركيب الصريح والتركيب التلقائي:
document.querySelectorAll('script[src*="recaptcha"]').forEach(s => {
if (s.src.includes('render=') && !s.src.includes('render=explicit')) {
console.log('Invisible/v3 reCAPTCHA detected in script:', s.src);
}
});
ما الذي يفرّقه عن reCAPTCHA v2 القياسي
| الخاصية | reCAPTCHA v2 القياسي | reCAPTCHA v2 Invisible |
|---|---|---|
| ودجت مرئي | نعم — مربع اختيار | لا — شارة فقط |
| تفاعل المستخدم | نقرة على المربع | تلقائي عند إرسال النموذج |
data-size |
normal أو compact |
invisible |
| نافذة التحدي | واردة دائمًا | عند الاشتباه في السلوك فقط |
| عنصر DOM | عنصر .g-recaptcha |
عنصر .g-recaptcha أو استدعاء برمجي |
الفارق الأهم عمليًا هو السطر الأخير: قد لا تترك النسخة غير المرئية أي عنصر في HTML، فيصبح فحص السكربتات إلزاميًا.
أرسل المهمة إلى CaptchaAI مع الراية invisible
المعامل الحاسم هو invisible=1. بدونه تُعامَل المهمة كنسخة قياسية، وقد يعود رمز يرفضه الموقع رغم أن الطلب نجح شكليًا. بقية المعاملات مألوفة: method=userrecaptcha مع googlekey وpageurl، ثم استطلاع دوري للنتيجة عبر res.php. وقت الحل المعلَن لهذا النوع أقل من 30 ثانية مع معدل نجاح مرتفع على الأنواع المدعومة، والفوترة قائمة على الـ threads المتزامنة لا على عدد عمليات الحل.
الرمز صالح لاستخدام واحد: لا تعِد إرساله في محاولة ثانية، واطلب رمزًا جديدًا لكل عملية إرسال.
Python
import requests
import time
API_KEY = "YOUR_API_KEY"
# Submit with invisible flag
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": "6Le-SITEKEY",
"pageurl": "https://example.com/login",
"invisible": "1", # critical for Invisible reCAPTCHA
"json": "1",
}).json()
if resp["status"] != 1:
raise Exception(f"Submit error: {resp['request']}")
task_id = resp["request"]
print(f"Submitted: {task_id}")
# Poll for result
for _ in range(24):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": task_id, "json": "1"
}).json()
if result["status"] == 1:
print(f"Token: {result['request'][:50]}...")
break
if result["request"] != "CAPCHA_NOT_READY":
raise Exception(f"Error: {result['request']}")
JavaScript
const axios = require('axios');
const resp = await axios.post('https://ocr.captchaai.com/in.php', null, {
params: {
key: 'YOUR_API_KEY',
method: 'userrecaptcha',
googlekey: '6Le-SITEKEY',
pageurl: 'https://example.com/login',
invisible: 1,
json: 1,
}
});
const taskId = resp.data.request;
console.log(`Submitted: ${taskId}`);
سيناريو تشغيلي: اختبار ليلي لبوابة تتبّع الشحنات
تخيّل فريق جودة في شركة شحن بالرياض يشغّل كل ليلة اختبارات على بيئة staging: تسجيل دخول، إنشاء شحنة، ثم تتبّعها. المسار كان يمرّ لأشهر، ثم بدأت خطوة تسجيل الدخول تفشل بعد تحديث من فريق الواجهة أضاف reCAPTCHA v2 Invisible إلى النموذج.
الفحص من وحدة التحكم يكشف السبب في ثوانٍ: لا يوجد عنصر .g-recaptcha، لكن شارة grecaptcha-badge موجودة، وsitekey مذكور داخل استدعاء grecaptcha.execute. بعد إضافة خطوة الحل مع invisible=1 إلى مُهيّئ الاختبارات، تعود الاختبارات الليلية إلى النجاح دون تعديل بقية السيناريو.
من حيث الحجم: 400 عملية إرسال ليلية موزّعة على نافذة ساعتين تُنفَّذ براحة على خطة BASIC ($15 شهريًا، 5 threads). أما إذا كان التشغيل متوازيًا وتتزاحم عشرات الطلبات في الدقيقة نفسها، فالانتقال إلى STANDARD ($30 شهريًا، 15 threads) هو ما يمنع تراكم قائمة الانتظار. الأسعار بالدولار الأمريكي.
احقن الرمز ثم شغّل رد النداء
الحصول على الرمز نصف العمل فقط. لأن النسخة غير المرئية مرتبطة بزر أو بعملية إرسال نموذج، فإن وضع القيمة في textarea[name="g-recaptcha-response"] لا يكفي: الموقع ينتظر تنفيذ الدالة المذكورة في data-callback، أو إرسال النموذج بعد ضبط الحقل.
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://example.com/login")
# After solving, inject and trigger
driver.execute_script("""
// Set the token
document.querySelector('textarea[name="g-recaptcha-response"]').value = arguments[0];
// Find and trigger the callback
var widget = document.querySelector('.g-recaptcha');
var callbackName = widget ? widget.getAttribute('data-callback') : null;
if (callbackName && typeof window[callbackName] === 'function') {
window[callbackName](arguments[0]);
}
""", token)
# Submit the form
driver.find_element(By.CSS_SELECTOR, "form#login").submit()
استدعِ رد النداء أولًا ثم أرسل النموذج؛ العكس يؤدي أحيانًا إلى إرسال الحقل قبل أن تُحدَّث حالة الودجت داخليًا.
حدّد العنصر الذي يشغّل التحقق
للتركيب نمطان اثنان فقط، ومعرفة أيّهما تستخدمه الصفحة تحدّد أين تحقن الرمز وأي دالة تستدعي. النمط الأول تعريفي: الزر نفسه يحمل الفئة والسمات.
<button class="g-recaptcha"
data-sitekey="6Le-SITEKEY"
data-callback="onSubmit"
data-size="invisible">
Submit
</button>
والنمط الثاني برمجي: مستمع حدث يستدعي grecaptcha.execute عند النقر.
// Site's code
document.getElementById('submit-btn').addEventListener('click', function() {
grecaptcha.execute();
});
افحص النمطين معًا قبل أن تبني منطق الحقن:
// Find elements with g-recaptcha class that are buttons
document.querySelectorAll('button.g-recaptcha, input.g-recaptcha').forEach(el => {
console.log('Trigger element:', el.tagName, el.textContent.trim());
console.log(' data-sitekey:', el.getAttribute('data-sitekey'));
console.log(' data-callback:', el.getAttribute('data-callback'));
});
أخطاء شائعة وسبب حدوثها
| العَرَض | السبب الأرجح | الإجراء |
|---|---|---|
| الموقع يرفض الرمز رغم نجاح الحل | الراية invisible=1 غير موجودة في الإرسال |
أضف "invisible": "1" إلى بيانات طلب in.php |
لا تجد sitekey في مصدر الصفحة |
لا يوجد عنصر .g-recaptcha |
ابحث عن grecaptcha.render() أو grecaptcha.execute() داخل السكربتات |
| النموذج يُرسل ثم يفشل بصمت | لم يُستدعَ رد النداء بعد الحقن | اقرأ قيمة data-callback ونفّذ الدالة يدويًا |
| لا أثر للاختبار في الصفحة | التحدي يظهر لحركة المرور المشبوهة فقط | تحقق من grecaptcha-badge أو من وسوم سكربت recaptcha |
الأسئلة الشائعة
رأيت render= في رابط السكربت — هل أرسلها كـ v3؟
ليس بالضرورة. المعامل render=SITEKEY يظهر في تركيب الإصدار الثالث، لكن الفيصل هو شكل الاستدعاء: النسخة غير المرئية من الإصدار الثاني تستدعي grecaptcha.execute() بلا معامل action، بينما يمرّر الإصدار الثالث دائمًا إجراءً مثل {action: 'submit'}. ابحث عن action داخل السكربت قبل اختيار طريقة الإرسال.
لماذا يُقبل الرمز في المتصفح ويُرفض على الخادم؟
ثلاثة أسباب متكررة:
- انقضاء صلاحية الرمز؛ عمره دقيقتان تقريبًا.
- اختلاف
pageurlالمرسل عن العنوان الفعلي للصفحة. - استهلاك الرمز مرة ثم إعادة استخدامه في محاولة ثانية.
اجعل خطوة الحل ملاصقة زمنيًا لخطوة الإرسال بدل تجهيز الرموز مسبقًا.
كم عدد الـ threads التي أحتاجها لـ 500 عملية إرسال يوميًا؟
الحساب يعتمد على التزامن لا على الإجمالي اليومي. مع وقت حل أقل من 30 ثانية، يكفي عدد صغير من الـ threads لتغطية هذا الحجم إن كانت الطلبات موزّعة على اليوم؛ خطة BASIC ($15 شهريًا، 5 threads) نقطة بداية معقولة، وتصبح الترقية مبرَّرة عندما تتزاحم الطلبات في نافذة قصيرة.
هل يمكن الحل دون تشغيل متصفح؟
نعم بالنسبة لخطوة الحل: sitekey وعنوان الصفحة كافيان لإرسال المهمة والحصول على الرمز عبر HTTP فقط. المتصفح يبقى مطلوبًا في الحالات التي يجب فيها حقن الرمز وتشغيل رد النداء داخل صفحة تعتمد على JavaScript لإتمام الإرسال.
ما أنواع CAPTCHA الأخرى التي يغطيها CaptchaAI؟
يشمل الدعم عائلة reCAPTCHA بنسخها v2 وv3 والمؤسسية، وCloudflare Turnstile وCloudflare Challenge، وGeeTest v3، واختبارات الصور والشبكة وBLS، إضافة إلى CaptchaFox وFriendly Captcha وLemin في مرحلة beta. في المقابل لا يدعم CaptchaAI حاليًا hCaptcha ولا FunCaptcha، ودعم GeeTest v4 معلَن كـ «قريبًا» وليس متاحًا بعد.
ابدأ التشغيل الآن
احصل على مفتاح الـ API من captchaai.com، ثم شغّل مثال Python أعلاه على نموذج اختباري قبل ربطه بخط الأتمتة.