في أغلب الحالات لا تكون الخدمة نفسها هي سبب فشل reCAPTCHA v2، بل التفاصيل المحيطة بالطلب: مفتاح موقع منسوخ من صفحة أخرى، أو عنوان صفحة لا يطابق موضع الأداة، أو توكن سليم أُرسل بعد فوات أوانه. لذلك فإن أسرع طريق للإصلاح هو قراءة رمز الخطأ بدقة ومطابقته مع سببه المباشر بدل تجربة الحلول عشوائيًا.
يصنّف هذا الدليل أعطال reCAPTCHA v2 إلى ثلاث مراحل — أخطاء إرسال الطلب، وأخطاء استطلاع النتيجة، ورفض الصفحة المستهدفة للتوكن — ويعطيك لكل رمز خطأ إصلاحًا محددًا. الفكرة أن تتوقف عن تخمين السبب، وتتعامل مع كل رمز خطأ كإشارة تدلّك على الخطوة التالية بدقة. إن كنت تبدأ للتوّ مع حلّ reCAPTCHA v2، فابدأ من دليل حلّ reCAPTCHA v2 عبر API ثم عُد إلى هذا المرجع عند أول خطأ يواجهك.
جدول تشخيص سريع حسب العَرَض
إن كان لديك رمز خطأ محدد بالفعل، فابدأ من هنا: ابحث عن العَرَض في العمود الأيمن ثم انتقل إلى أول ما ينبغي فحصه. تجد أسفل الجدول شرحًا موسّعًا لكل حالة مع أمثلة الكود.
| العَرَض | أول ما تتحقق منه |
|---|---|
ERROR_GOOGLEKEY أو ERROR_WRONG_GOOGLEKEY |
هل نُسِخ مفتاح الموقع بدقة من data-sitekey؟ |
ERROR_PAGEURL |
هل ضمّنت عنوان الصفحة الكامل؟ |
ERROR_BAD_TOKEN_OR_PAGEURL |
هل الأداة داخل iframe؟ استخدم عنوان الـ iframe. |
CAPCHA_NOT_READY لأكثر من 3 دقائق |
طبيعي في التحديات الصعبة؛ ارفع المهلة إلى 180 ثانية. |
ERROR_CAPTCHA_UNSOLVABLE |
أرسِل مهمة جديدة، وإن تكرر فتحقق من مفتاح الموقع وعنوان الصفحة. |
| التوكن يعمل لكنّ الصفحة لا تتفاعل | ابحث عن data-callback واستدعِ وظيفة رد النداء. |
| التوكن يعود لكنّ النموذج يفشل | قد يكون التوكن منتهيًا (> دقيقتين)؛ أرسِل أسرع. |
| أعطال متقطعة | أضِف منطق إعادة المحاولة بمعرّفات مهام جديدة. |
الأسباب الجذرية الأربعة لأغلب حالات الفشل
قبل الغوص في رموز الأخطاء الفردية، اعلم أنّ نحو 80% من حالات فشل reCAPTCHA v2 تعود إلى واحد من أربعة أسباب فقط:
- مفتاح الموقع (
googlekey) خاطئ أو مفقود — منسوخ من صفحة أخرى أو فارغ، فترفض الخدمة المهمة فورًا برمزERROR_GOOGLEKEYأوERROR_WRONG_GOOGLEKEY. - عنوان الصفحة (
pageurl) غير مطابق — لا يشير إلى الموضع الدقيق الذي تُحمَّل عنده الأداة، خصوصًا حين تكون داخل iframe على نطاق مختلف، فيظهرERROR_PAGEURLأوERROR_BAD_TOKEN_OR_PAGEURL. - رد النداء (Callback) لم يُستدعَ — تنتظر الصفحة وظيفة رد نداء JavaScript بينما تكتفي أنت بملء الحقل المخفي
g-recaptcha-response، فلا يُرسَل النموذج أبدًا. - توكن منتهي الصلاحية أو معاد الاستخدام — توكنات reCAPTCHA صالحة لمرة واحدة وتنتهي صلاحيتها بعد دقيقتين تقريبًا، فيرفضها الموقع المستهدف بصمت إن تأخّر الإرسال أو تكرّر استخدام توكن قديم.
كيف تستخرج مفتاح الموقع الصحيح
مفتاح الموقع (googlekey) هو أكثر القيم التي يُخطئ فيها المطورون، لأنه يُنسخ أحيانًا من صفحة أخرى أو من نسخة قديمة من الأداة. يأتي هذا المفتاح من سمة data-sitekey في أداة reCAPTCHA، أو من المعلمة k داخل عنوان URL للارتساء.
افحص مصدر الصفحة، وابحث عن أحد الموضعين التاليين لتلتقط القيمة الصحيحة مباشرةً بدل الاعتماد على قيمة قديمة:
# Look for data-sitekey in the page HTML
# <div class="g-recaptcha" data-sitekey="6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-"></div>
# Or find it in the anchor URL
# https://www.google.com/recaptcha/api2/anchor?k=6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-
أخطاء مرحلة إرسال الطلب (in.php)
تظهر هذه الأخطاء عند إرسال مهمة CAPTCHA إلى https://ocr.captchaai.com/in.php، وكلها مرتبطة بمعلمات الطلب أو حالة الحساب.
| رمز الخطأ | السبب | الإصلاح |
|---|---|---|
ERROR_WRONG_USER_KEY |
صيغة مفتاح API غير صالحة (ليست 32 حرفًا) | تحقق من مفتاحك عبر captchaai.com/api.php |
ERROR_KEY_DOES_NOT_EXIST |
المفتاح غير مسجّل في النظام | تأكد من نسخ المفتاح كاملًا دون مسافات زائدة |
ERROR_ZERO_BALANCE |
رصيد الحساب صفر | اشحن رصيدك أو راجع عدد الـ Threads النشطة |
ERROR_PAGEURL |
المعلمة pageurl مفقودة |
أضِف عنوان الصفحة الكامل الذي تظهر فيه الأداة |
ERROR_GOOGLEKEY |
googlekey مشوّه أو فارغ |
استخرج مفتاح الموقع الصحيح من الصفحة |
ERROR_WRONG_GOOGLEKEY |
المعلمة googlekey غائبة تمامًا |
أضِف googlekey إلى طلبك |
ERROR_BAD_TOKEN_OR_PAGEURL |
زوج googlekey + pageurl غير متطابق |
تحقق مما إذا كانت الأداة داخل iframe واستخدم عنوانه |
ERROR_BAD_PARAMETERS |
معلمات مطلوبة ناقصة أو مشوّهة | راجع مستندات API للحقول المطلوبة |
قبل معالجة أي رمز في الكود، تحقق سريعًا من هذه النقاط الثلاث:
- تأكد أنّ مفتاح الـ API مكوّن من 32 حرفًا بلا مسافات زائدة قبله أو بعده.
- أرسِل
googlekeyوpageurlمعًا في الطلب نفسه، لا في طلبين منفصلين. - راجع رصيدك وعدد الـ Threads النشطة قبل أي إرسال مكثّف.
مثال: طلب سليم مع معالجة الأخطاء
import requests
def submit_recaptcha_v2(api_key, sitekey, page_url):
response = requests.get("https://ocr.captchaai.com/in.php", params={
"key": api_key,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"json": 1
})
data = response.json()
if data.get("status") == 1:
return data["request"] # task ID
error = data.get("request", "UNKNOWN_ERROR")
if error == "ERROR_WRONG_USER_KEY":
raise ValueError("API key format is invalid. Must be 32 characters.")
elif error == "ERROR_ZERO_BALANCE":
raise RuntimeError("Account balance is zero. Top up at captchaai.com")
elif error == "ERROR_PAGEURL":
raise ValueError("pageurl parameter is missing from request")
elif error in ("ERROR_GOOGLEKEY", "ERROR_WRONG_GOOGLEKEY"):
raise ValueError(f"Invalid sitekey. Verify the data-sitekey value on the page.")
elif error == "ERROR_BAD_TOKEN_OR_PAGEURL":
raise ValueError("Sitekey/pageurl mismatch. Check if widget is in an iframe.")
else:
raise RuntimeError(f"API error: {error}")
# Usage
task_id = submit_recaptcha_v2("YOUR_API_KEY", "6Le-wvkSAAAAAN...", "https://example.com/login")
print(f"Task submitted: {task_id}")
async function submitRecaptchaV2(apiKey, sitekey, pageUrl) {
const params = new URLSearchParams({
key: apiKey,
method: "userrecaptcha",
googlekey: sitekey,
pageurl: pageUrl,
json: 1,
});
const res = await fetch(`https://ocr.captchaai.com/in.php?${params}`);
const data = await res.json();
if (data.status === 1) return data.request;
const error = data.request || "UNKNOWN_ERROR";
const fixes = {
ERROR_WRONG_USER_KEY: "API key format is invalid. Must be 32 characters.",
ERROR_ZERO_BALANCE: "Account balance is zero. Top up at captchaai.com",
ERROR_PAGEURL: "pageurl parameter is missing from request",
ERROR_GOOGLEKEY: "Invalid sitekey. Check the data-sitekey attribute.",
ERROR_BAD_TOKEN_OR_PAGEURL: "Sitekey/pageurl mismatch. Check iframe context.",
};
throw new Error(fixes[error] || `API error: ${error}`);
}
// Usage
const taskId = await submitRecaptchaV2("YOUR_API_KEY", "6Le-wvkSAAAAAN...", "https://example.com/login");
console.log(`Task submitted: ${taskId}`);
أخطاء مرحلة استطلاع النتيجة (res.php)
تظهر هذه الأخطاء عند استطلاع النتيجة من https://ocr.captchaai.com/res.php بعد إرسال المهمة بنجاح.
| رمز الخطأ | السبب | الإصلاح |
|---|---|---|
CAPCHA_NOT_READY |
الحل ما زال جاريًا | انتظر 5 ثوانٍ ثم استطلِع مجددًا؛ هذا سلوك طبيعي |
ERROR_CAPTCHA_UNSOLVABLE |
تعذّر حلّ الاختبار | أرسِل مهمة جديدة بمعلمات محدّثة |
ERROR_WRONG_ID_FORMAT |
صيغة معرّف المهمة غير صالحة | تحقق من المعرّف العائد من in.php |
ERROR_WRONG_CAPTCHA_ID |
معرّف المهمة غير موجود | تأكد من حفظ المعرّف الصحيح |
ERROR_EMPTY_ACTION |
المعلمة action=get مفقودة |
أضِف action=get إلى طلب الاستطلاع |
راعِ هذه القواعد الثلاث أثناء الاستطلاع كي لا تحوّل سلوكًا طبيعيًا إلى خطأ:
- عامِل
CAPCHA_NOT_READYكحالة طبيعية لا كخطأ؛ انتظر ثم أعِد الاستطلاع. - أرسِل
action=getمع معرّف المهمة الصحيح في كل طلب استطلاع. - ارفع المهلة إلى 180 ثانية في التحديات الصعبة بدل إلغاء المهمة مبكرًا.
مثال: استطلاع النتيجة مع معالجة سليمة للأخطاء
import time
import requests
def poll_result(api_key, task_id, timeout=120):
start = time.time()
while time.time() - start < timeout:
time.sleep(5)
response = requests.get("https://ocr.captchaai.com/res.php", params={
"key": api_key,
"action": "get",
"id": task_id,
"json": 1
})
data = response.json()
if data.get("status") == 1:
return data["request"] # solved token
error = data.get("request", "")
if error == "CAPCHA_NOT_READY":
continue # normal — keep waiting
elif error == "ERROR_CAPTCHA_UNSOLVABLE":
raise RuntimeError("CAPTCHA unsolvable. Submit a new task with fresh params.")
elif error in ("ERROR_WRONG_ID_FORMAT", "ERROR_WRONG_CAPTCHA_ID"):
raise ValueError(f"Invalid task ID: {task_id}")
else:
raise RuntimeError(f"Polling error: {error}")
raise TimeoutError(f"Solve timed out after {timeout}s")
# Usage
token = poll_result("YOUR_API_KEY", task_id)
print(f"Token: {token[:50]}...")
async function pollResult(apiKey, taskId, timeout = 120000) {
const start = Date.now();
while (Date.now() - start < timeout) {
await new Promise((r) => setTimeout(r, 5000));
const params = new URLSearchParams({
key: apiKey,
action: "get",
id: taskId,
json: 1,
});
const res = await fetch(`https://ocr.captchaai.com/res.php?${params}`);
const data = await res.json();
if (data.status === 1) return data.request;
if (data.request === "CAPCHA_NOT_READY") continue;
if (data.request === "ERROR_CAPTCHA_UNSOLVABLE")
throw new Error("Unsolvable. Submit a new task.");
throw new Error(`Polling error: ${data.request}`);
}
throw new Error(`Solve timed out after ${timeout / 1000}s`);
}
عندما يرفض الموقع توكنًا سليمًا
أصعب الحالات هي أن تعيد الخدمة توكنًا صحيحًا بينما يرفضه الموقع المستهدف. هنا لا يوجد رمز خطأ من الخدمة، لأنها ترى أنّ كل شيء تمّ بنجاح، والخلل يكمن في طريقة تسليم التوكن للصفحة نفسها. راقب سلوك النموذج في المتصفح، وابدأ من الأسباب الأربعة التالية:
- التوكن أُدرج في الحقل الخطأ.
- رد النداء لم يُطلَق رغم ملء الحقل المخفي.
- التوكن انتهت صلاحيته قبل الإرسال.
- الأداة محمّلة داخل iframe من نطاق مختلف.
التوكن أُدرج في الحقل الخطأ
تبحث بعض الصفحات عن التوكن في منطقة النص g-recaptcha-response، بينما تعتمد أخرى على grecaptcha.getResponse()، وثالثة تنتظر رد نداء. فإذا اخترت طريقة الإدراج الخطأ، فسيفشل إرسال النموذج بصمت.
- الإصلاح — افحص الصفحة ثم أدرِج التوكن في الحقل المخفي
g-recaptcha-response. - إن وُجدت سمة
data-callback، فاستدعِ وظيفة رد النداء المذكورة فيها بدل الحقل المخفي. - أو اكتب القيمة في حقل النموذج مباشرةً ثم أرسله يدويًا، كما توضّح الطرق الثلاث التالية:
# Method 1: Hidden field injection
driver.execute_script(
'document.getElementById("g-recaptcha-response").innerHTML = arguments[0];',
token
)
# Method 2: Callback execution (check data-callback attribute)
driver.execute_script(f'onCaptchaSuccess("{token}");')
# Method 3: Direct form field + submit
driver.execute_script(
'document.querySelector("[name=g-recaptcha-response]").value = arguments[0];',
token
)
driver.find_element("css selector", "form").submit()
رد النداء لم يُطلَق
إذا كانت الأداة تحمل data-callback="onSuccess" أو تستخدم grecaptcha.render() مع خاصية callback، فإنّ ملء الحقل المخفي وحده لا يُحرّك شيئًا؛ عليك استدعاء وظيفة رد النداء مباشرة.
- الإصلاح — ابحث عن اسم رد النداء داخل سمة
data-callbackعلى الأداة. - استدعِ الوظيفة مباشرةً ومرِّر إليها التوكن كما في المثال التالي:
// In browser console or Puppeteer/Playwright
// Check for data-callback
const widget = document.querySelector('.g-recaptcha');
const callbackName = widget?.getAttribute('data-callback');
if (callbackName && window[callbackName]) {
window[callbackName](token);
}
التوكن انتهت صلاحيته
إذا مرّ أكثر من دقيقتين تقريبًا بين استلام التوكن وإرسال النموذج، رفضته Google. وهذا شائع في مسارات الأتمتة البطيئة أو المزدحمة بالخطوات.
- الإصلاح — أرسِل النموذج فور استلام التوكن.
- إن كان مسارك بطيئًا، فاطلب الحل قرب خطوة الإرسال بدل بدايته حتى لا يشيخ التوكن.
الأداة محمّلة داخل iframe
إذا حُمِّلت reCAPTCHA داخل iframe من نطاق مختلف، فعليك استخدام عنوان مصدر الـ iframe قيمةً لـ pageurl لا عنوان الصفحة الأم. وعادةً يشير الخطأ ERROR_BAD_TOKEN_OR_PAGEURL إلى هذه الحالة تحديدًا؛ وهو سبب متكرر لسكربت يعمل محليًا على بوابة خدمات إلكترونية ثم يفشل بعد نقله إلى خادم سحابي.
- الإصلاح — افحص الصفحة وحدّد إطار iframe الذي يحوي reCAPTCHA.
- انسخ عنوان
srcالخاص به واستخدمه قيمةً لـpageurl، ثم اختبر السكربت في البيئة نفسها التي سيعمل فيها فعليًا.
الأسئلة الشائعة
كيف أتأكد أنّ googlekey وpageurl متطابقان مع الصفحة الفعلية؟
- افتح الصفحة في المتصفح، واستخرج
data-sitekeyمن عنصرg-recaptchaمباشرةً بدل الاعتماد على قيمة قديمة. - تأكد أنّ
pageurlيطابق العنوان الظاهر في شريط المتصفح عند تحميل الأداة. - إن كانت الأداة داخل iframe، فخُذ عنوان مصدره لا عنوان الصفحة الأم.
لماذا ينجح الحلّ على جهازي المحلي ويفشل على الخادم السحابي؟
الفرق غالبًا في البيئة لا في الكود. تخيّل سكربتًا يعبّئ نموذج تسجيل على بوابة خدمات إلكترونية ويعمل محليًا، ثم يبدأ بإرجاع ERROR_BAD_TOKEN_OR_PAGEURL فور نقله إلى خادم سحابي؛ السبب عادةً أنّ الأداة داخل iframe من نطاق فرعي وأنت ترسل عنوان الصفحة الأم. راجع قيمة pageurl المُرسَلة فعليًا من الخادم، وقلّل الفجوة الزمنية بين استلام التوكن وإرساله.
ما مدة صلاحية توكن reCAPTCHA v2، ومتى يُرفض؟
يبقى التوكن صالحًا نحو دقيقتين ولمرة استخدام واحدة فقط. يُرفض إذا أُرسل بعد انتهاء المهلة، أو أُعيد استخدامه في أكثر من طلب، أو لم يُمرَّر إلى الحقل أو رد النداء الذي تنتظره الصفحة.
متى يكون تكرار ERROR_CAPTCHA_UNSOLVABLE مؤشرًا على مشكلة إعداد؟
- خطأ منفرد أمر عادي، وحلّه بإرسال مهمة جديدة بمعلمات محدّثة.
- تكراره على نفس الصفحة يعني عادةً مفتاح موقع أو عنوان صفحة غير مطابق، أو نوعًا مختلفًا من CAPTCHA — مثل reCAPTCHA v2 Enterprise الذي يتطلب إعدادًا خاصًا.
- تحقق من هذه العناصر قبل إعادة المحاولة، ولا تُعِد استخدام معرّف المهمة القديم لأنه لن يغيّر النتيجة.
أصلِح سير عمل reCAPTCHA v2
ابدأ حلّ reCAPTCHA v2 مع CaptchaAI بعد الحصول على مفتاح API من captchaai.com/api.php، ثم طبّق هذه الخطوات الأربع على مسارك:
- تحقق من مدخلاتك — استخرج
googlekeyمنdata-sitekey، واستخدم عنوان الصفحة الدقيق مع الانتباه إلى إطارات iframe. - حدّد طريقة الإدراج — اعرف هل تتوقع الصفحة حقلًا مخفيًا أم رد نداء أم كليهما.
- أرسِل فورًا — استخدم التوكن خلال دقيقتين من استلامه.
- أضِف معالجة للأخطاء — استعن بأمثلة الكود أعلاه لالتقاط كل رمز خطأ والتعامل معه.