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

ERROR_WRONG_GOOGLEKEY: تشخيص الخطأ وإصلاحه في reCAPTCHA

عندما يرفض CaptchaAI مهمة reCAPTCHA ويعيد ERROR_WRONG_GOOGLEKEY، فالسبب في الغالبية العظمى من الحالات واحد: مفتاح الموقع (sitekey) الذي أرسلته لا يطابق المفتاح الذي حمّلته الصفحة المستهدفة فعلياً. قبل أن تشكّ في الكود أو في الخدمة، ابدأ بهذه الخطوات الثلاث التي تحلّ أغلب الحالات:

  1. أعد استخراج المفتاح من الصفحة نفسها لحظة الإرسال بدل الاعتماد على قيمة قديمة مخزَّنة
  2. تأكّد أن المفتاح مأخوذ من النموذج الصحيح، لا من iframe أو من نطاق فرعي مختلف
  3. طابِق نوع الإرسال مع نوع الودجت: enterprise=1 لمفاتيح Enterprise وinvisible=1 للنسخة غير المرئية

نصيحة عملية: عامل مفتاح الموقع كقيمة متغيّرة تُقرأ عند كل تشغيل، لا كثابت يُكتب مرة واحدة في ملف الإعداد. هذا وحده يمنع معظم حالات هذا الخطأ.


أسباب خطأ ERROR_WRONG_GOOGLEKEY

الخطأ ليس عطلاً في CaptchaAI، بل إشارة إلى أن قيمة googlekey المرسَلة لا تصف الصفحة الحقيقية. الأسباب الأكثر تكراراً هي:

  • مفتاح مستخرَج بشكل خاطئ — القيمة لا تطابق مصدر الصفحة المستهدفة أصلاً.
  • مفتاح Enterprise أُرسل كمفتاح قياسي — الصفحة تستخدم Enterprise وتحتاج المعلمة enterprise=1.
  • عدم تطابق مع النسخة غير المرئية — الودجت مخفية وتحتاج المعلمة invisible=1.
  • مفتاح ديناميكي تغيّر بعد الاستخراج — الموقع دوّر المفتاح منذ لحظة قراءته.
  • مفتاح من صفحة أو نطاق مختلف — مأخوذ من iframe أو من مجال آخر لا يخصّ الصفحة.
  • مفتاح قديم مثبّت في الكود — كان صالحاً في السابق ثم جرى استبداله.

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


جدول التشخيص السريع

عند مواجهة الخطأ، اربط العرض الظاهر بالسبب المرجّح ثم بالإجراء المباشر قبل الدخول في التفاصيل:

العرَض السبب المرجّح الإجراء
المفتاح يبدو صحيحاً والخطأ مستمر مفتاح Enterprise أضف enterprise=1
المفتاح يتغيّر بين زيارة وأخرى مفتاح ديناميكي استخرج مفتاحاً جديداً في كل مرة
أكثر من مفتاح على الصفحة اختيار المفتاح الخاطئ طابِق المفتاح مع النموذج الصحيح
المفتاح مأخوذ من iframe عبر CDN مفتاح نطاق مختلف استخرجه من الصفحة الرئيسية لا من iframe
المفتاح المستخرَج فارغ الصفحة تُبنى بـ JavaScript استخدم Selenium لاستخراجه

يكشف هذا الجدول الحالة الغالبة بسرعة، لكن التأكيد يبقى عبر مقارنة المفتاح المرسَل بما تحمّله الصفحة فعلاً. لا تعتمد على الشكل وحده — طابِق القيمة مع المصدر.


استخرج مفتاح الموقع الصحيح

الطريقة الأولى: البحث في مصدر الصفحة

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

import re
import requests


def extract_sitekey(page_url):
    """Extract reCAPTCHA sitekey from page source."""
    resp = requests.get(page_url, timeout=15)
    html = resp.text

    # Pattern 1: data-sitekey attribute
    match = re.search(r'data-sitekey="([^"]+)"', html)
    if match:
        return match.group(1)

    # Pattern 2: grecaptcha.render call
    match = re.search(r"grecaptcha\.render\([^,]+,\s*\{[^}]*sitekey['\"]?\s*:\s*['\"]([^'\"]+)", html)
    if match:
        return match.group(1)

    # Pattern 3: grecaptcha.execute call
    match = re.search(r"grecaptcha\.execute\(['\"]([^'\"]+)", html)
    if match:
        return match.group(1)

    # Pattern 4: reCAPTCHA script src
    match = re.search(r"recaptcha/api\.js\?render=([^&\"]+)", html)
    if match:
        return match.group(1)

    return None


sitekey = extract_sitekey("https://example.com/login")
print(f"Sitekey: {sitekey}")

الطريقة الثانية: أدوات مطوّري المتصفح (DevTools)

عندما تريد التحقق يدوياً وبسرعة، افتح الصفحة في المتصفح واقرأ المفتاح مباشرة من العناصر:

  1. افتح الصفحة المستهدفة في Chrome
  2. اضغط F12 ثم انتقل إلى تبويب العناصر
  3. اضغط Ctrl+F وابحث عن sitekey
  4. حدّد سمة data-sitekey="..."
  5. انسخ القيمة (سلسلة أبجدية رقمية من نحو 40 حرفاً)

الطريقة الثالثة: تبويب الشبكة (Network)

إذا كانت الصفحة تحمّل الودجت عبر طلبات لاحقة، فالمفتاح يظهر في عنوان طلب الشبكة نفسه:

  1. افتح F12 ثم انتقل إلى تبويب الشبكة
  2. فلتر النتائج بكلمة recaptcha
  3. ابحث عن طلبات google.com/recaptcha/api2/anchor
  4. اقرأ المعلمة k= من عنوان URL — هذه هي قيمة مفتاح الموقع

تحقّق من المفتاح قبل الإرسال

قبل أن ترسل أي مفتاح إلى الـ API، تأكّد أنه غير فارغ وأن صيغته مقبولة. هذا الفحص البسيط يوفّر عليك محاولات فاشلة ورسائل خطأ متكررة:

import re


def validate_sitekey(sitekey):
    """Validate sitekey format before API call."""
    if not sitekey:
        raise ValueError("Sitekey is empty")

    # Standard format: 40 alphanumeric + hyphens/underscores
    if not re.match(r'^[a-zA-Z0-9_-]{20,60}$', sitekey):
        raise ValueError(f"Invalid sitekey format: {sitekey}")

    return True


# Use before solving
sitekey = extract_sitekey("https://example.com/login")
validate_sitekey(sitekey)

التعامل مع reCAPTCHA Enterprise

مفاتيح Enterprise متطابقة في الشكل مع المفاتيح القياسية، لكنها تحتاج إلى المعلمة enterprise. الفرق الحقيقي يظهر في اسم السكربت الذي تحمّله الصفحة، لذا افحصه أولاً ثم أضف العلم المناسب:

انتبه: نسيان المعلمة enterprise=1 على صفحة تستخدم Enterprise هو أكثر سبب خفيّ لهذا الخطأ، لأن المفتاح يبدو صحيحاً تماماً ويمرّ من فحص الصيغة دون مشكلة.

import requests

# Standard reCAPTCHA — loads via recaptcha/api.js
# Enterprise reCAPTCHA — loads via recaptcha/enterprise.js

def detect_enterprise(page_url):
    """Detect if page uses reCAPTCHA Enterprise."""
    resp = requests.get(page_url, timeout=15)
    return "recaptcha/enterprise.js" in resp.text


# Submit with enterprise flag
is_enterprise = detect_enterprise("https://example.com")

data = {
    "key": "YOUR_API_KEY",
    "method": "userrecaptcha",
    "googlekey": sitekey,
    "pageurl": "https://example.com",
    "json": 1,
}

if is_enterprise:
    data["enterprise"] = 1

resp = requests.post("https://ocr.captchaai.com/in.php", data=data)

التعامل مع reCAPTCHA غير المرئية

النسخة غير المرئية لا تعرض المربّع التقليدي، لكنها تظل بحاجة إلى المعلمة invisible=1 حتى يعالجها CaptchaAI بشكل صحيح. تعرّف عليها من مؤشرات محددة في مصدر الصفحة:

def detect_invisible(html):
    """Detect invisible reCAPTCHA."""
    indicators = [
        'data-size="invisible"',
        "grecaptcha.execute(",
        "recaptcha/api.js?render=",
    ]
    return any(i in html for i in indicators)


# Submit with invisible flag
data = {
    "key": "YOUR_API_KEY",
    "method": "userrecaptcha",
    "googlekey": sitekey,
    "pageurl": "https://example.com",
    "invisible": 1,
    "json": 1,
}

استخراج المفتاح الديناميكي المحمّل عبر JavaScript

بعض المواقع لا تضع المفتاح في HTML الأولي، بل تحقنه عبر JavaScript بعد تحميل الصفحة. في هذه الحالة يعيد طلب requests البسيط قيمة فارغة، وتحتاج إلى متصفح مؤتمت يشغّل السكربتات فعلياً:

from selenium import webdriver
from selenium.webdriver.common.by import By


def extract_dynamic_sitekey(url):
    """Extract sitekey from JavaScript-rendered page."""
    driver = webdriver.Chrome()
    driver.get(url)

    # Wait for reCAPTCHA to load
    import time
    time.sleep(3)

    # Try data-sitekey attribute
    elements = driver.find_elements(By.CSS_SELECTOR, "[data-sitekey]")
    if elements:
        sitekey = elements[0].get_attribute("data-sitekey")
        driver.quit()
        return sitekey

    # Try iframe src parameter
    iframes = driver.find_elements(By.CSS_SELECTOR, "iframe[src*='recaptcha']")
    for iframe in iframes:
        src = iframe.get_attribute("src")
        import re
        match = re.search(r'[?&]k=([^&]+)', src)
        if match:
            driver.quit()
            return match.group(1)

    driver.quit()
    return None

سيناريو عملي: خطأ ظهر بعد نشر تحديث

تخيّل فريقاً في القاهرة أو الرياض يشغّل اختبارات انحدار (regression) على صفحة تسجيل الدخول الخاصة بمنتجه. كان مفتاح الموقع مثبّتاً في ملف الإعداد ويعمل منذ أشهر، ثم بدأ فجأة بإرجاع ERROR_WRONG_GOOGLEKEY بعد نشر تحديث للواجهة الأمامية. السبب أن أداة البناء أعادت توليد الودجت بمفتاح موقع جديد، بينما ظل السكربت يرسل المفتاح القديم المخزَّن.

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


خلاصة سريعة قبل إعادة الإرسال

راجِع هذه النقاط كقائمة تحقق نهائية قبل أن تعيد المحاولة:

  • استخرج المفتاح من الصفحة الحيّة لا من قيمة محفوظة سابقاً
  • تأكّد أن pageurl والمفتاح من البيئة نفسها (اختبار أو إنتاج)
  • افحص السكربت: recaptcha/api.js قياسي وrecaptcha/enterprise.js يعني Enterprise
  • تحقّق من صيغة المفتاح برمجياً قبل الإرسال لتفادي القيم الفارغة

الأسئلة الشائعة

لماذا يستمر الخطأ رغم أن مفتاح الموقع يبدو صحيحاً؟

غالباً لأن المفتاح صحيح لكن نوعه لا يطابق طريقة الإرسال. إذا كان الموقع يستخدم reCAPTCHA Enterprise فأنت بحاجة إلى المعلمة enterprise=1، وإذا كان يستخدم النسخة غير المرئية فأنت بحاجة إلى invisible=1. أضف المعلمة المناسبة وأعد المحاولة قبل أن تشكّ في المفتاح نفسه.

هل يختلف مفتاح الموقع بين بيئتي الاختبار والإنتاج؟

نعم في كثير من المشاريع. تستخدم بيئة الاختبار (staging) مفتاح موقع مسجَّلاً على نطاق مختلف عن الإنتاج. إرسال مفتاح الإنتاج مع صفحة اختبار — أو العكس — يُنتج ERROR_WRONG_GOOGLEKEY. تأكّد دائماً أن المفتاح وقيمة pageurl من البيئة نفسها.

كيف أميّز مفتاح reCAPTCHA Enterprise عن المفتاح القياسي؟

لا يمكن التمييز من شكل المفتاح لأنه مطابق في الطول والصيغة. الفرق يظهر في السكربت الذي تحمّله الصفحة: النسخة القياسية تُحمَّل عبر recaptcha/api.js، بينما تُحمَّل نسخة Enterprise عبر recaptcha/enterprise.js، وهو ما تفحصه الدالة detect_enterprise تلقائياً.

ماذا أفعل إذا كان الموقع يحمّل المفتاح عبر JavaScript؟

لن يظهر المفتاح في مصدر HTML الأولي، لذا سيعيد طلب requests قيمة فارغة. استخدم متصفحاً مؤتمتاً مثل Selenium لتحميل الصفحة بالكامل، ثم اقرأ سمة data-sitekey أو المعلمة k= من الـ iframe كما في الدالة extract_dynamic_sitekey.


أدلة ذات صلة


  • أرسل مفتاح الموقع الصحيح إلى CaptchaAI واحصل على استجابة reCAPTCHA جاهزة — ابدأ الآن.*
التعليقات غير مفعّلة لهذا المقال.