دروس API

حل reCAPTCHA v2 Enterprise مع Node.js وCaptchaAI

معامل واحد يفصل reCAPTCHA v2 Enterprise عن الإصدار القياسي: أضف enterprise=1 إلى طلب in.php، ثم أكمل المسار المعتاد — احفظ معرّف المهمة، استطلع res.php، واحقن الرمز في الحقل g-recaptcha-response. لا يوجد endpoint خاص بـ Enterprise ولا مكتبة إضافية ولا صيغة طلب مختلفة.

الفارق الحقيقي يظهر بعد الحل لا قبله: نسخة Enterprise تمرّ عبر الواجهة الخلفية لـ Google بتسجيل مخاطر أدق، فيرتبط الرمز بسياق الجلسة التي حُلّ فيها — وعلى رأسه ترويسة User-Agent. من هنا تأتي أغلب حالات «الرمز عاد سليماً لكن الموقع رفضه».


v2 القياسي مقابل v2 Enterprise: أين يختلفان فعلياً

النقطة reCAPTCHA v2 القياسي reCAPTCHA v2 Enterprise
مسار السكربت /recaptcha/api2/ /recaptcha/enterprise/
معامل الإرسال لا شيء إضافي enterprise=1
ارتباط الرمز مرن نسبياً مرتبط بترويسة User-Agent الخاصة بالحل
سقف وقت الحل لدى CaptchaAI أقل من 60 ثانية أقل من 60 ثانية

لن تفرّق بين النسختين بالعين المجردة؛ المكان الموثوق الوحيد للتمييز هو تبويب الشبكة داخل DevTools.


ما تحتاجه قبل السطر الأول

العنصر التفاصيل
مفتاح CaptchaAI API 32 حرفاً تنسخها من لوحة تحكم حسابك
Node.js 14 أو أحدث مع fetch المدمج أو حزمة node-fetch
مفتاح الموقع قيمة k= من رابط anchor الخاص بـ Enterprise
عنوان الصفحة الرابط الكامل الذي يظهر فيه اختبار CAPTCHA
الإجراء — اختياري قيمة sa= إن وُجدت في الرابط

الخطوة 1: التقط توقيع Enterprise من الشبكة

افتح DevTools على تبويب الشبكة، أعد تحميل الصفحة، وابحث عن طلب anchor:

https://www.google.com/recaptcha/enterprise/anchor?ar=1&k=6LdxxXXxAAAAAAcX...&sa=LOGIN&...

كل معامل في هذا الرابط يقابل حقلاً سترسله بعد قليل:

المؤشر ما يعنيه لك
/recaptcha/enterprise.js أو /enterprise/anchor أنت أمام Enterprise لا أمام v2 القياسي
k= مفتاح الموقع الذي سترسله في googlekey
sa= الإجراء الذي سترسله في action

إذا ظهر لك /recaptcha/api2/anchor فأنت أمام الإصدار القياسي: لا ترسل معه enterprise=1، لأن الإرسال بمعامل لا يخصّ الودجت ينتهي غالباً بالخطأ ERROR_CAPTCHA_UNSOLVABLE.


الخطوة 2: أرسل المهمة إلى CaptchaAI

const API_KEY = "YOUR_API_KEY";

async function submitTask(sitekey, pageurl, action) {
  const params = new URLSearchParams({
    key: API_KEY,
    method: "userrecaptcha",
    googlekey: sitekey,
    pageurl: pageurl,
    enterprise: "1",
    json: "1",
  });

  if (action) {
    params.set("action", action);
  }

  const response = await fetch(
    `https://ocr.captchaai.com/in.php?${params}`
  );
  const data = await response.json();

  if (data.status !== 1) {
    throw new Error(`Submit failed: ${data.request}`);
  }

  console.log(`Task submitted. ID: ${data.request}`);
  return data.request;
}

ما يستحق الانتباه هنا:

  • method يبقى userrecaptcha لكل عائلة reCAPTCHA بما فيها Enterprise.
  • enterprise هو المعامل الوحيد الذي يغيّر مسار التحقق داخل الخدمة.
  • json=1 يجعل الاستجابة قابلة للقراءة البرمجية بدل النص الخام.
  • action يُضاف عند وجوده فعلاً؛ اختراع قيمة له يضرّ ولا ينفع.

الاستجابة الناجحة تعيد status: 1 مع معرّف المهمة في الحقل request؛ احتفظ به للخطوة التالية.


الخطوة 3: استطلع النتيجة بإيقاع منضبط

انتظر 20 ثانية قبل أول استطلاع، ثم اسأل كل 5 ثوانٍ:

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

async function pollResult(taskId) {
  await delay(20000);

  for (let attempt = 0; attempt < 30; attempt++) {
    const params = new URLSearchParams({
      key: API_KEY,
      action: "get",
      id: taskId,
      json: "1",
    });

    const response = await fetch(
      `https://ocr.captchaai.com/res.php?${params}`
    );
    const data = await response.json();

    if (data.status === 1) {
      console.log(`Solved. Token: ${data.request.substring(0, 60)}...`);
      return {
        token: data.request,
        userAgent: data.user_agent || "",
      };
    }

    if (data.request !== "CAPCHA_NOT_READY") {
      throw new Error(`Solve failed: ${data.request}`);
    }

    console.log(`Attempt ${attempt + 1}: not ready, waiting 5s...`);
    await delay(5000);
  }

  throw new Error("Solve timed out");
}

الإيقاع مقصود: الاستطلاع كل ثانية لا يعجّل الحل، وإنما يستهلك حصتك من الطلبات.

تذكّر أن CAPCHA_NOT_READY — بهذا الإملاء تحديداً — تعني أن المهمة ما زالت قيد العمل، وأي رد آخر يعني توقفها.

تعمل CaptchaAI مع reCAPTCHA v2 Enterprise ضمن سقف أقل من 60 ثانية بمعدل نجاح مرتفع على الأنواع المدعومة، فثلاثون محاولة على مسافة 5 ثوانٍ هامش كافٍ.


الخطوة 4: احقن الرمز في الطلب النهائي

أرسل الرمز في الحقل g-recaptcha-response، ومرّر قيمة user_agent العائدة من الخدمة داخل ترويسات طلبك:

async function submitForm(token, userAgent) {
  const headers = { "Content-Type": "application/x-www-form-urlencoded" };

  if (userAgent) {
    headers["User-Agent"] = userAgent;
  }

  const response = await fetch("https://example.com/api/login", {
    method: "POST",
    headers,
    body: new URLSearchParams({
      username: "user",
      password: "pass",
      "g-recaptcha-response": token,
    }),
  });

  console.log(`Response status: ${response.status}`);
  return response;
}

هذه النقطة هي الفاصل بين حلٍّ ناجح وآخر يُرفض عند الاستخدام: رمز Enterprise مرتبط ببيئة الحل، فإذا اختلفت ترويسة User-Agent قرأ الموقع السياق على أنه غير متطابق وردّ الطلب.


السكربت الكامل جاهزاً للتشغيل

يجمع المثال التالي الخطوات الأربع في ملف واحد؛ بدّل المفتاح ورابط الصفحة ثم شغّله:

const API_KEY = "YOUR_API_KEY";
const SITE_KEY = "6LdxxXXxAAAAAAcXxxXxxX91xxxxxxxx8xxOx7A";
const PAGE_URL = "https://example.com/login";
const ACTION = "LOGIN"; // optional — omit if not in anchor URL

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

async function solveRecaptchaV2Enterprise() {
  // Submit task
  const submitParams = new URLSearchParams({
    key: API_KEY,
    method: "userrecaptcha",
    googlekey: SITE_KEY,
    pageurl: PAGE_URL,
    enterprise: "1",
    action: ACTION,
    json: "1",
  });

  const submitRes = await fetch(
    `https://ocr.captchaai.com/in.php?${submitParams}`
  );
  const submitData = await submitRes.json();

  if (submitData.status !== 1) {
    throw new Error(`Submit error: ${submitData.request}`);
  }

  const taskId = submitData.request;
  console.log(`Task ID: ${taskId}`);

  // Poll for result
  await delay(20000);

  for (let i = 0; i < 30; i++) {
    const pollParams = new URLSearchParams({
      key: API_KEY,
      action: "get",
      id: taskId,
      json: "1",
    });

    const pollRes = await fetch(
      `https://ocr.captchaai.com/res.php?${pollParams}`
    );
    const pollData = await pollRes.json();

    if (pollData.status === 1) {
      return {
        token: pollData.request,
        userAgent: pollData.user_agent || "",
      };
    }

    if (pollData.request !== "CAPCHA_NOT_READY") {
      throw new Error(`Solve error: ${pollData.request}`);
    }

    await delay(5000);
  }

  throw new Error("Solve timed out");
}

(async () => {
  const { token, userAgent } = await solveRecaptchaV2Enterprise();
  console.log(`Token: ${token.substring(0, 60)}...`);
  if (userAgent) console.log(`User-Agent: ${userAgent}`);
})();

الناتج المتوقع:

Task ID: 73849562810
Token: 03AGdBq24PBCqLmOx2V4pGHJjkR2xZ1r...
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)...

حدود الدعم التي يجب معرفتها مسبقاً

اضبط توقعاتك قبل بناء مسار أتمتة كامل حول الخدمة:

النوع الحالة لدى CaptchaAI
reCAPTCHA v2 وv2 Invisible وv2 Enterprise وv3 وv3 Enterprise مدعومة عبر userrecaptcha
Cloudflare Turnstile وChallenge، GeeTest v3، الصور والشبكة، BLS مدعومة
CaptchaFox وFriendly Captcha وLemin beta فقط — بلا أرقام منشورة
hCaptcha ❌ غير مدعوم حالياً
FunCaptcha — Arkose Labs ❌ غير مدعوم حالياً
GeeTest v4 غير متاح بعد — مُعلن كخدمة قادمة

وإذا خلطت صفحتك أكثر من نوع، خطّط لمسار بديل للأنواع غير المدعومة.


أخطاء شائعة وكيف تقرأها

الخطأ السبب الغالب المعالجة
ERROR_WRONG_USER_KEY تنسيق المفتاح غير صالح تأكد أن المفتاح 32 حرفاً منسوخاً بالكامل من لوحة التحكم
ERROR_KEY_DOES_NOT_EXIST المفتاح غير معروف للخدمة راجع المفتاح في حسابك على CaptchaAI
ERROR_ZERO_BALANCE الرصيد غير كافٍ جدّد الاشتراك أو أضف رصيداً قبل تشغيل الدُفعة
ERROR_BAD_TOKEN_OR_PAGEURL مفتاح موقع أو رابط صفحة خاطئ انسخ قيمة k= من رابط anchor لا من الشيفرة المصدرية
ERROR_CAPTCHA_UNSOLVABLE تعذّر إنجاز المهمة تحقق أن المفتاح فعلاً Enterprise ثم أعد المحاولة بتباعد متزايد
الموقع يرفض رمزاً سليماً عدم تطابق User-Agent استخدم user_agent العائد مع نتيجة الحل

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


سيناريو تشغيلي من السوق العربي

تخيّل فريق QA في متجر إلكتروني خليجي يشغّل اختبار انحدار ليلياً على صفحة تسجيل الدخول ومسار إتمام الشراء، وكلاهما محمي بـ reCAPTCHA v2 Enterprise. الفريق يعمل من الأحد إلى الخميس، والتشغيل مجدول عند الثانية فجراً بتوقيت الخليج، مع موجة إضافية قبل رمضان والجمعة البيضاء. الإعداد العملي يقوم على أربع نقاط:

  1. قدّر التزامن لا المجموع. فوترة CaptchaAI قائمة على عدد الـ threads المتزامنة مع عمليات حل غير محدودة داخل كل thread، فالسؤال ليس «كم عملية شهرياً» بل «كم عملية في اللحظة نفسها».
  2. ابدأ صغيراً ثم قِس. خطة BASIC ($15 شهريًا، 5 threads) تكفي اختبارات ليلية متواضعة، ومع عشرات المتصفحات المتوازية تصبح ADVANCE ($90 شهريًا، 50 thread) الخيار الأقرب.
  3. احسب السقف الزمني. بسقف أقل من 60 ثانية للعملية، ينجز كل thread نحو 60 عملية في الساعة عند الاستغلال الكامل؛ اطرح منها زمن التنقل داخل الصفحة.
  4. راعِ الواجهات العربية. صفحات RTL قد تضع الودجت داخل حاوية مختلفة أو إطار مضمّن، لذلك التقط k= من رابط anchor لا من موضع العنصر على الشاشة.

والفاتورة تبقى ثابتة مهما ارتفع عدد الاختبارات، لأنها مرتبطة بعدد الـ threads لا بعدد عمليات الحل.


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

كم عدد الـ threads الذي يناسب 300 عملية حل في الساعة؟

بسقف أقل من 60 ثانية للعملية، يغطي كل thread نحو 60 عملية في الساعة، أي أن 5 threads هي الحد النظري الأدنى. اترك هامشاً للتباطؤ الشبكي وابدأ من خطة أوسع قليلاً.

ماذا أفعل عندما تنتهي المهلة قبل عودة النتيجة؟

  • سجّل معرّف المهمة في سجلاتك قبل إنهاء الحلقة.
  • أوقف الاستطلاع بدل إطالته إلى ما لا نهاية.
  • أرسل مهمة جديدة بتباعد متزايد بين المحاولات.

استطلاع مهمة قديمة بلا نهاية يستهلك الطلبات دون نتيجة، والإرسال من جديد أسرع وأرخص.

هل أحتاج متصفحاً حقيقياً مثل Puppeteer أو Playwright؟

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

هل يختلف التعامل مع نسخة Enterprise غير المرئية؟

منطق الإرسال نفسه: userrecaptcha مع enterprise=1. الفرق أن الودجت بلا مربع اختيار، فتلتقط k= من رابط anchor أو من وسم السكربت، ويجري الحقن برمجياً.


ابدأ التشغيل الآن

أنشئ حسابك على CaptchaAI، انسخ مفتاح الـ API، وأضف enterprise=1 إلى أول طلب v2 لديك.


أدلة ذات صلة

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