دروس API

حل reCAPTCHA v2 مع Callback باستخدام CaptchaAI API

تستخدم بعض مواقع الويب reCAPTCHA v2 وظيفة رد الاتصال بدلاً من الحقل المخفي القياسي g-recaptcha-response. عند حل اختبار CAPTCHA وإدخال الرمز المميز في الحقل المخفي، لا يحدث شيء - تتجاهله الصفحة. وذلك لأن الموقع يتوقع منك استدعاء وظيفة JavaScript باستخدام الرمز المميز بدلاً من ذلك.

يوضح لك هذا الدليل كيفية اكتشاف reCAPTCHA v2 المستند إلى رد الاتصال، وحلها من خلال واجهة برمجة تطبيقات CaptchaAI، واستدعاء رد الاتصال بشكل صحيح. يتطابق استدعاء واجهة برمجة التطبيقات (API) مع reCAPTCHA v2 القياسي - فقط خطوة إدخال الرمز المميز هي التي تتغير.

هل أنت جديد على reCAPTCHA v2؟ ابدأ بـكيفية حل reCAPTCHA v2 باستخدام APIللتدفق القياسي، ثم عد هنا لمتغير رد الاتصال.


ما تحتاجه قبل البدء

المتطلبات التفاصيل
مفتاح CaptchaAI API احصل على واحدة منcaptchaai.com/api.php. سلسلة مكونة من 32 حرفًا.
عنوان URL للصفحة المستهدفة عنوان URL الكامل حيث يتم تحميل عنصر واجهة المستخدم reCAPTCHA v2.
مفتاح الموقع reCAPTCHA v2 المفتاح العام مرتبط بمثيل القطعة.
أداة أتمتة المتصفح السيلينيوم أو Puppeteer أو Playwright - تحتاج إلى تنفيذ JavaScript لاستدعاء رد الاتصال.
** اسم وظيفة رد الاتصال ** وظيفة JavaScript التي يتوقع الموقع أن تتلقى الرمز المميز.

كيفية التعرف على تنفيذ رد الاتصال

يكتب معيار reCAPTCHA v2 الرمز المميز الذي تم حله في منطقة نص g-recaptcha-response المخفية. تتخطى تطبيقات رد الاتصال ذلك وتستدعي وظيفة JavaScript مباشرةً. هنا هو كيفية معرفة الفرق.

الطريقة الأولى: التحقق من سمة data-callback

افحص قسم أداة reCAPTCHA في مصدر الصفحة:

<div class="g-recaptcha"
     data-sitekey="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
     data-callback="SubmitToken">
</div>

في حالة وجود data-callback، يستخدم الموقع رد اتصال. القيمة (SubmitToken) هي اسم الوظيفة التي تحتاجها.

الطريقة الثانية: التحقق من مكالمات grecaptcha.render()

ابحث في JavaScript للصفحة عن grecaptcha.render:

grecaptcha.render('recaptcha-container', {
  sitekey: '6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-',
  callback: userVerified
});

الخاصية callback تسمي الدالة. في هذه الحالة، userVerified.

الطريقة الثالثة: فحص تكوين reCAPTCHA الداخلي

افتح وحدة تحكم المتصفح على الصفحة المستهدفة وقم بتشغيل:

___grecaptcha_cfg.clients[0]

انتقل إلى شجرة الكائنات للعثور على خاصية callback. يختلف المسار الدقيق حسب الموقع — قد يكون clients[0].aa.l.callback أو أي شيء آخر اعتمادًا على إصدار reCAPTCHA وتصغيره. إذا كانت الصفحة تحتوي على عدة مثيلات reCAPTCHA، فتحقق من clients[1] وclients[2] وما إلى ذلك.

سكريبت الكشف السريع

قم بتشغيل هذا في وحدة تحكم المتصفح للعثور على أسماء رد الاتصال تلقائيًا:

// Check data-callback attributes
document.querySelectorAll('[data-callback]').forEach(el => {
  console.log('data-callback:', el.getAttribute('data-callback'));
});

// Check internal config
if (typeof ___grecaptcha_cfg !== 'undefined') {
  Object.keys(___grecaptcha_cfg.clients).forEach(key => {
    const client = ___grecaptcha_cfg.clients[key];
    console.log(`Client ${key}:`, JSON.stringify(client, null, 2));
  });
}

كيف يختلف حل رد الاتصال عن الإصدار القياسي v2

استدعاء API إلى CaptchaAI ** متطابق **. والفرق الوحيد هو ما تفعله بالرمز المميز بعد استلامه.

خطوة قياسي v2 رد الاتصال v2
1. أرسل إلى CaptchaAI method=userrecaptcha + مفتاح الموقع + عنوان URL للصفحة نفسه
2. استطلاع النتيجة action=get + معرف كلمة التحقق نفسه
3. تلقي الرمز المميز نفس تنسيق الرمز المميز نفسه
4. إدخال الرمز المميز قم بتعيين قيمة الحقل g-recaptcha-response استدعاء وظيفة رد الاتصال باستخدام الرمز المميز
5. أرسل النموذج إرسال نموذج المحفّز عادة ما يكون تلقائياً، حيث يقوم رد الاتصال بالتعامل معه

حرج: لا تقم بتعيين g-recaptcha-response على التطبيقات المستندة إلى رد الاتصال. تتجاهل الصفحة هذا الحقل وتنتظر تشغيل وظيفة رد الاتصال. سيؤدي تعيين الحقل دون استدعاء رد الاتصال إلى جعل الأمر يبدو وكأن اختبار CAPTCHA لم يتم حله مطلقًا.


حل التدفق

Page → extract sitekey + pageurl + callback name
                    ↓
      POST to in.php (method=userrecaptcha)
                    ↓
           receive captcha ID
                    ↓
         wait 15–20 seconds
                    ↓
      GET res.php (action=get, id=…)
          ↓                    ↓
   CAPCHA_NOT_READY       status=1 → token
    (wait 5s, retry)            ↓
                     invoke callback(token)
                              ↓
               site processes token automatically

تنفيذ بايثون (السيلينيوم)

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

API_KEY = "YOUR_CAPTCHAAI_API_KEY"
SITEKEY = "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
PAGE_URL = "https://example.com/login"
CALLBACK_NAME = "SubmitToken"  # The callback function name from the page

SUBMIT_URL = "https://ocr.captchaai.com/in.php"
RESULT_URL = "https://ocr.captchaai.com/res.php"


def solve_recaptcha_v2(api_key, sitekey, pageurl):
    """Submit a reCAPTCHA v2 task and return the solved token."""

    # Step 1: Submit the captcha
    submit_resp = requests.post(
        SUBMIT_URL,
        data={
            "key": api_key,
            "method": "userrecaptcha",
            "googlekey": sitekey,
            "pageurl": pageurl,
            "json": 1,
        },
        timeout=30,
    )
    submit_resp.raise_for_status()
    submit_data = submit_resp.json()

    if submit_data.get("status") != 1:
        raise RuntimeError(f"Submit failed: {submit_data}")

    captcha_id = submit_data["request"]
    print(f"Task created — captcha ID: {captcha_id}")

    # Step 2: Wait before first poll
    time.sleep(15)

    # Step 3: Poll for result
    for _ in range(60):
        result_resp = requests.get(
            RESULT_URL,
            params={
                "key": api_key,
                "action": "get",
                "id": captcha_id,
                "json": 1,
            },
            timeout=30,
        )
        result_resp.raise_for_status()
        result_data = result_resp.json()

        if result_data.get("request") == "CAPCHA_NOT_READY":
            time.sleep(5)
            continue

        if result_data.get("status") == 1:
            return result_data["request"]

        raise RuntimeError(f"Polling error: {result_data}")

    raise TimeoutError("reCAPTCHA v2 solve timed out")


def detect_callback_name(driver):
    """Detect the reCAPTCHA callback function name from the page."""

    # Try data-callback attribute first
    callback = driver.execute_script("""
        const el = document.querySelector('[data-callback]');
        if (el) return el.getAttribute('data-callback');
        return null;
    """)
    if callback:
        return callback

    # Try internal reCAPTCHA config
    callback = driver.execute_script("""
        if (typeof ___grecaptcha_cfg === 'undefined') return null;
        const clients = ___grecaptcha_cfg.clients;
        for (const key of Object.keys(clients)) {
            const client = clients[key];
            // Walk the object tree to find a callback function
            const json = JSON.stringify(client);
            const match = json.match(/"callback":"(\\w+)"/);
            if (match) return match[1];
        }
        return null;
    """)
    return callback


# Main workflow
driver = webdriver.Chrome()
driver.get(PAGE_URL)

# Detect the callback name (or use the known name)
detected = detect_callback_name(driver)
callback_name = detected or CALLBACK_NAME
print(f"Using callback: {callback_name}")

# Solve the CAPTCHA
token = solve_recaptcha_v2(API_KEY, SITEKEY, PAGE_URL)
print(f"Solved token: {token[:80]}...")

# Invoke the callback with the token
driver.execute_script(f"{callback_name}(arguments[0]);", token)
print("Callback invoked — site should process the token automatically")

# Wait for the page to process
time.sleep(3)
driver.quit()

ماذا يفعل:

  1. يرسل مفتاح الموقع وعنوان URL للصفحة إلى in.php باستخدام method=userrecaptcha — المطابق للإصدار v2.
  2. استطلاعات res.php كل 5 ثوانٍ حتى يصبح الرمز المميز جاهزًا.
  3. يكتشف اسم وظيفة رد الاتصال من صفحة DOM.
  4. يستدعي وظيفة رد الاتصال باستخدام الرمز المميز الذي تم حله باستخدام execute_script.
  5. وتتولى JavaScript الخاصة بالموقع التعامل مع الباقي — إرسال النموذج، أو التحقق من الصحة، أو إعادة توجيه الصفحة.

تنفيذ Node.js (Puppeteer)

const puppeteer = require("puppeteer");

const API_KEY = "YOUR_CAPTCHAAI_API_KEY";
const SITEKEY = "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-";
const PAGE_URL = "https://example.com/login";
const CALLBACK_NAME = "SubmitToken";

const SUBMIT_URL = "https://ocr.captchaai.com/in.php";
const RESULT_URL = "https://ocr.captchaai.com/res.php";

function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

async function solveRecaptchaV2(apiKey, sitekey, pageurl) {
  // Step 1: Submit the captcha
  const submitResp = await fetch(SUBMIT_URL, {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: new URLSearchParams({
      key: apiKey,
      method: "userrecaptcha",
      googlekey: sitekey,
      pageurl: pageurl,
      json: "1",
    }),
  });

  const submitData = await submitResp.json();
  if (submitData.status !== 1) {
    throw new Error(`Submit failed: ${JSON.stringify(submitData)}`);
  }

  const captchaId = submitData.request;
  console.log(`Task created — captcha ID: ${captchaId}`);

  // Step 2: Wait before first poll
  await sleep(15_000);

  // Step 3: Poll for result
  for (let i = 0; i < 60; i++) {
    const resultResp = await fetch(
      `${RESULT_URL}?${new URLSearchParams({
        key: apiKey,
        action: "get",
        id: captchaId,
        json: "1",
      })}`
    );

    const resultData = await resultResp.json();

    if (resultData.request === "CAPCHA_NOT_READY") {
      await sleep(5_000);
      continue;
    }

    if (resultData.status === 1) {
      return resultData.request;
    }

    throw new Error(`Polling error: ${JSON.stringify(resultData)}`);
  }

  throw new Error("reCAPTCHA v2 solve timed out");
}

async function detectCallbackName(page) {
  return page.evaluate(() => {
    // Try data-callback attribute
    const el = document.querySelector("[data-callback]");
    if (el) return el.getAttribute("data-callback");

    // Try internal config
    if (typeof ___grecaptcha_cfg !== "undefined") {
      const clients = ___grecaptcha_cfg.clients;
      for (const key of Object.keys(clients)) {
        const json = JSON.stringify(clients[key]);
        const match = json.match(/"callback":"(\w+)"/);
        if (match) return match[1];
      }
    }

    return null;
  });
}

(async () => {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();
  await page.goto(PAGE_URL, { waitUntil: "networkidle2" });

  // Detect callback
  const detected = await detectCallbackName(page);
  const callbackName = detected || CALLBACK_NAME;
  console.log(`Using callback: ${callbackName}`);

  // Solve the CAPTCHA
  const token = await solveRecaptchaV2(API_KEY, SITEKEY, PAGE_URL);
  console.log(`Solved token: ${token.slice(0, 80)}...`);

  // Invoke the callback
  await page.evaluate(
    (name, tkn) => {
      window[name](tkn);
    },
    callbackName,
    token
  );
  console.log("Callback invoked — site should process the token automatically");

  await sleep(3_000);
  await browser.close();
})();

تنفيذ PHP

استدعاء API هو نفسه في PHP. يتطلب استدعاء رد الاتصال سياق متصفح، لذا يغطي هذا المثال الحل من جانب الخادم. استخدم أداة متصفح مقطوعة الرأس (على سبيل المثال، PHP WebDriver) لخطوة الحقن.

<?php
$apiKey  = "YOUR_CAPTCHAAI_API_KEY";
$sitekey = "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-";
$pageurl = "https://example.com/login";

// Step 1: Submit
$submit = file_get_contents("https://ocr.captchaai.com/in.php?" . http_build_query([
    "key"       => $apiKey,
    "method"    => "userrecaptcha",
    "googlekey" => $sitekey,
    "pageurl"   => $pageurl,
    "json"      => 1,
]));

$submitData = json_decode($submit, true);
if ($submitData["status"] !== 1) {
    die("Submit failed: " . $submit);
}

$captchaId = $submitData["request"];
echo "Task created — captcha ID: $captchaId\n";

// Step 2: Wait and poll
sleep(15);

for ($i = 0; $i < 60; $i++) {
    $result = file_get_contents("https://ocr.captchaai.com/res.php?" . http_build_query([
        "key"    => $apiKey,
        "action" => "get",
        "id"     => $captchaId,
        "json"   => 1,
    ]));

    $resultData = json_decode($result, true);

    if ($resultData["request"] === "CAPCHA_NOT_READY") {
        sleep(5);
        continue;
    }

    if ($resultData["status"] === 1) {
        $token = $resultData["request"];
        echo "Solved token: " . substr($token, 0, 80) . "...\n";
        // Pass $token to your browser automation to invoke the callback
        break;
    }

    die("Polling error: " . $result);
}

بعد الحصول على الرمز المميز في PHP، استخدم أداة أتمتة المتصفح (على سبيل المثال، php-webdriver) لتنفيذ ما يلي:

SubmitToken("TOKEN_FROM_CAPTCHAAI");

الأخطاء الشائعة

# خطأ ماذا يحدث إصلاح
1 إعداد g-recaptcha-response بدلاً من استدعاء رد الاتصال تتجاهل الصفحة الرمز المميز — لا يتم إرسال النموذج مطلقًا ابحث عن اسم رد الاتصال واستدعاه باستخدام الرمز المميز
2 اسم وظيفة رد الاتصال خاطئ خطأ JavaScript: الوظيفة غير محددة أعد التحقق من data-callback أو grecaptcha.render() أو التكوين الداخلي
3 رد الاتصال موجود على فهرس عميل مختلف مثيل reCAPTCHA خاطئ مستهدف على صفحات متعددة الأدوات تحقق من ___grecaptcha_cfg.clients[1]، clients[2]، وما إلى ذلك.
4 استدعاء رد الاتصال قبل أن تصبح الصفحة جاهزة لم يتم تعريف الوظيفة بعد في سياق الصفحة انتظر DOMContentLoaded أو networkidle قبل الاستدعاء
5 استخدام اسم /minified المبهم اسم رد الاتصال في المصدر مشوه استخدم وحدة تحكم متصفح وقت التشغيل للعثور على مرجع الوظيفة الفعلي
6 ** مزج رد الاتصال v2 مع v2 غير المرئي ** تستخدم بعض التطبيقات غير المرئية أيضًا عمليات الاسترجاعات تحقق مما إذا كان data-size="invisible" موجودًا — إذا كان الأمر كذلك، راجعكيفية حل reCAPTCHA Invisible باستخدام API

استكشاف الأخطاء وإصلاحها

تم حل الرمز ولكن الصفحة لا تتفاعل

السبب الأكثر شيوعًا: قيامك بتعيين g-recaptcha-response بدلاً من استدعاء رد الاتصال. تحقق مما إذا كانت الأداة تحتوي على data-callback أو callback في grecaptcha.render(). إذا حدث ذلك، يجب عليك استدعاء هذه الوظيفة.

ReferenceError: SubmitToken is not defined

لم يتم تحميل وظيفة رد الاتصال بعد أو أن الاسم خاطئ. حاول:

  1. قم بتأكيد الاسم عن طريق فحص data-callback أو التكوين الداخلي.
  2. انتظر حتى يتم تحميل الصفحة بالكامل قبل الاستدعاء.
  3. في المواقع المصغرة، قد يتم تعيين الوظيفة لمتغير - تحقق من window.SubmitToken في وحدة التحكم.

يعمل الرمز المميز على الإصدار 2 القياسي ولكنه يفشل في هذه الصفحة

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

ERROR_BAD_TOKEN_OR_PAGEURL

زوج sitekey/pageurl غير صالح. هذا خطأ في واجهة برمجة التطبيقات (API)، ولا يتعلق برد الاتصال مقابل المعيار. أعد استخراج القيمتين من الصفحة.

تحتوي الصفحة على العديد من أدوات reCAPTCHA

قد يكون لكل عنصر واجهة مستخدم رد الاتصال الخاص به. قم بفحص كل قسم g-recaptcha أو تحقق من ___grecaptcha_cfg.clients لجميع المثيلات المسجلة. قم بمطابقة الأداة مع النموذج الذي تستهدفه.

ERROR_CAPTCHA_UNSOLVABLE

لا يمكن حل التحدي. أعد المحاولة بطلب جديد. هذا ليس خاصًا برد الاتصال.

للحصول على مرجع الخطأ الكامل، راجعأخطاء حل reCAPTCHA v2 الشائعة.


لماذا يعمل CaptchaAI لهذا الغرض

عامل التفاصيل
** نفس استدعاء API ** يتطابق تدفق Submit/poll مع reCAPTCHA v2 القياسي — لا حاجة إلى معلمات إضافية
نسبة النجاح 99.5%+ لـ reCAPTCHA v2 (رد الاتصال والمعيار يستخدم نفس الحل)
** حل السرعة ** أقل من 60 ثانية
** التوافق الرمزي ** يعمل الرمز المميز الذي تم إرجاعه مع كل من حقن g-recaptcha-response واستدعاء رد الاتصال
التسعير تبدأ الخطط القائمة على سلاسل المحادثات من 15/month للحلول غير المحدودة

الرمز المميز الذي يُرجعه CaptchaAI هو نفسه بغض النظر عن كيفية تنفيذ الموقع لـ reCAPTCHA v2. يكمن الاختلاف بالكامل في التعليمات البرمجية من جانب العميل، وهي كيفية تسليم الرمز المميز إلى الصفحة.


مثال كامل قابل للتشغيل

هل تحتاج إلى مشروع عمل كامل مع إعداد البيئة والاستقصاء وإعادة المحاولة ومعالجة الأخطاء؟

راجع المثال الكامل القابل للتشغيل على GitHub →


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

ما هو رد الاتصال reCAPTCHA v2؟

رد الاتصال هو إحدى وظائف JavaScript التي يسجلها موقع الويب لتلقي رمز reCAPTCHA الذي تم حله. بدلاً من كتابة الرمز المميز في حقل g-recaptcha-response المخفي، يقوم reCAPTCHA باستدعاء الوظيفة مباشرةً. تقوم الوظيفة عادةً بتشغيل إرسال النموذج أو التحقق من الصحة أو إعادة توجيه الصفحة.

كيف يختلف رد الاتصال عن reCAPTCHA v2 القياسي لاستدعاء API؟

انها ليست مختلفة على الاطلاق. يمكنك إرسال نفس طلب method=userrecaptcha باستخدام نفس مفتاح الموقع وعنوان URL للصفحة. والفرق الوحيد هو ما تفعله بالرمز المميز بعد استلامه - حيث تقوم باستدعاء وظيفة رد الاتصال بدلاً من تعيين قيمة الحقل.

كيف يمكنني العثور على اسم وظيفة رد الاتصال؟

ثلاثة أماكن للتحقق: (1) سمة data-callback في قسم reCAPTCHA، (2) خاصية callback في استدعاء grecaptcha.render() في صفحة JavaScript، (3) كائن ___grecaptcha_cfg.clients[0] في وحدة تحكم المتصفح - انتقل إلى الشجرة للعثور على خاصية callback.

هل يمكنني استخدام الرمز المميز بكلا الطريقتين؟

الرمز المميز نفسه يعمل في كلتا الحالتين. ولكن إذا كان الموقع يتوقع رد اتصال، فسيتم تجاهل إعداد g-recaptcha-response. قم دائمًا بمطابقة طريقة الحقن مع ما يتوقعه الموقع.

هل أحتاج إلى متصفح لاستدعاء رد الاتصال؟

نعم. رد الاتصال هو وظيفة JavaScript في سياق الصفحة. أنت بحاجة إلى السيلينيوم، أو Puppeteer، أو Playwright، أو أداة مشابهة يمكنها تشغيل JavaScript على الصفحة المستهدفة.


ابدأ في حل رد الاتصال reCAPTCHA v2

  1. الحصول على مفتاح API الخاص بكcaptchaai.com/api.php
  2. اكتشف اسم رد الاتصال — تحقق من data-callback أو grecaptcha.render() أو التكوين الداخلي
  3. انسخ كود Python أو Node.js أعلاه — استبدل العناصر النائبة بمفتاحك، ومفتاح الموقع، ورابط الصفحة، واسم رد الاتصال
  4. قم بتشغيله — يصل الرمز المميز في أقل من 60 ثانية، ويتم تشغيل رد الاتصال، وتعالج الصفحة النتيجة
  5. ** عالقة؟ ** ابدأ بـأخطاء حل reCAPTCHA v2 الشائعةأو قراءة كاملةمستندات CaptchaAI API

مقالات ذات صلة

أدلة ذات صلة

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