التكاملات

Axios + CaptchaAI: حل CAPTCHA بدون متصفح

حل CAPTCHA على الخادم لا يستلزم متصفحاً على الإطلاق: أرسل المهمة إلى CaptchaAI عبر طلب HTTP، استطلع النتيجة كل بضع ثوانٍ، ثم مرّر الرمز الناتج إلى النموذج المستهدف. مكتبة Axios وحدها تكفي لتغطية هذه الدورة كاملة في Node.js — من reCAPTCHA v2 وv3 إلى Cloudflare Turnstile وكابتشا الصور. النتيجة مسار خفيف يعمل داخل خدمة خلفية أو مهمة مجدولة أو دالة serverless دون أي عبء تشغيلي لمتصفح كامل.

لماذا تحل CAPTCHA عبر HTTP دون متصفح؟

المتصفح المؤتمَت مثل Puppeteer أو Playwright يستهلك بين 200 و500 ميجابايت من الذاكرة لكل نسخة، ويضيف زمن إقلاع وتحديثات هشّة كلما تغيّرت بنية صفحة الهدف. في المقابل، لا يتجاوز استهلاك مسار HTTP النقي مع CaptchaAI نحو 5 ميجابايت، أي كفاءة أعلى بمقدار 40 إلى 100 مرة على الخادم. لهذا يناسب هذا النهج المهام الخلفية والجداول الزمنية والدوال قصيرة العمر التي تعمل على خادم افتراضي متواضع.

تخيّل فريقاً في القاهرة أو الرياض يراقب توافر المقاعد أو تحديث الأسعار على بوابة محمية بـ reCAPTCHA. تشغيل عشرات نسخ المتصفح على خادم واحد يستنزف الذاكرة بسرعة، بينما يتيح الحل عبر HTTP تشغيل المسار نفسه على خطة استضافة صغيرة مع هامش واسع للتوسّع لاحقاً. العملية بأكملها ليست أكثر من دورة إرسال ثم استطلاع ثم استخدام الرمز.

المتطلبات

المتطلب التفاصيل
Node.js 16+
Axios 1.x
مفتاح CaptchaAI API أنشئ مفتاحك من هنا
npm install axios

بناء عميل CaptchaAI

اجمع دورة الإرسال والاستطلاع في صنف (class) واحد قابل لإعادة الاستخدام. يرسل التابع submit المهمة إلى نقطة النهاية in.php ويعيد معرّف المهمة، بينما يستطلع poll نقطة res.php حتى تجهز النتيجة أو تنتهي المهلة. التابع solve يجمع الخطوتين، وgetBalance يقرأ الرصيد المتبقي في الحساب.

const axios = require("axios");

class CaptchaAI {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = "https://ocr.captchaai.com";
  }

  async submit(params) {
    params.key = this.apiKey;
    const resp = await axios.get(`${this.baseUrl}/in.php`, { params });
    const text = resp.data;

    if (!String(text).startsWith("OK|")) {
      throw new Error(`Submit failed: ${text}`);
    }
    return String(text).split("|")[1];
  }

  async poll(taskId, timeoutMs = 300000) {
    const deadline = Date.now() + timeoutMs;
    const params = { key: this.apiKey, action: "get", id: taskId };

    while (Date.now() < deadline) {
      await new Promise((r) => setTimeout(r, 5000));

      const resp = await axios.get(`${this.baseUrl}/res.php`, { params });
      const text = String(resp.data);

      if (text === "CAPCHA_NOT_READY") continue;
      if (text.startsWith("OK|")) return text.split("|").slice(1).join("|");
      throw new Error(`Solve failed: ${text}`);
    }
    throw new Error(`Timeout after ${timeoutMs}ms for task ${taskId}`);
  }

  async solve(params, timeoutMs = 300000) {
    const taskId = await this.submit(params);
    return this.poll(taskId, timeoutMs);
  }

  async getBalance() {
    const resp = await axios.get(`${this.baseUrl}/res.php`, {
      params: { key: this.apiKey, action: "getbalance" },
    });
    return parseFloat(resp.data);
  }
}

module.exports = CaptchaAI;

يبقى هذا العميل ثابتاً بين جميع الأنواع؛ ما يتغيّر لاحقاً هو حقول params التي ترسلها في كل نوع من أنواع CAPTCHA.

حل reCAPTCHA v2 دون متصفح

استخرج sitekey من الصفحة المستهدفة، مرّره مع عنوان الصفحة في method: "userrecaptcha"، ثم أرفق الرمز الناتج في الحقل g-recaptcha-response عند إرسال النموذج عبر Axios. لا حاجة لأي واجهة رسومية في أي خطوة.

const CaptchaAI = require("./captchaai");

async function main() {
  const solver = new CaptchaAI(process.env.CAPTCHAAI_API_KEY);

  // Solve the CAPTCHA without opening any browser
  const token = await solver.solve({
    method: "userrecaptcha",
    googlekey: "6Le-wvkS...",
    pageurl: "https://example.com/login",
  });

  // Submit form with the token using Axios
  const resp = await axios.post("https://example.com/login", {
    username: "user",
    password: "pass",
    "g-recaptcha-response": token,
  });

  console.log(`Login response: ${resp.status}`);
}

main().catch(console.error);

حل Cloudflare Turnstile دون متصفح

النمط نفسه مع تبديل الحقول: استخدم method: "turnstile" ومرّر sitekey وعنوان الصفحة، ثم أرسل الرمز في الحقل cf-turnstile-response الذي يتوقعه خادم Cloudflare.

const token = await solver.solve({
  method: "turnstile",
  sitekey: "0x4AAAAA...",
  pageurl: "https://example.com",
});

// Submit with Turnstile token
const resp = await axios.post("https://example.com/api/verify", {
  "cf-turnstile-response": token,
  data: "payload",
});

حل كابتشا الصور من الخادم

لكابتشا الصور، اقرأ الملف وحوّله إلى base64 قبل إرساله في body. تعيد الخدمة النص المقروء مباشرةً بدلاً من رمز، فترفقه في حقل النموذج المناسب.

const fs = require("fs");

const imageBuffer = fs.readFileSync("captcha.png");
const imageB64 = imageBuffer.toString("base64");

const text = await solver.solve({
  method: "base64",
  body: imageB64,
});

console.log(`CAPTCHA text: ${text}`);

// Submit form with solved text
const resp = await axios.post("https://example.com/verify", {
  captcha: text,
  other_data: "value",
});

سير عمل كامل لاستخراج البيانات

يجمع المثال التالي الدورة كلها: يجلب الصفحة، يقرأ sitekey من الشيفرة عبر cheerio، يحل reCAPTCHA، ثم يعيد إرسال النموذج بكامل حقوله مضافاً إليها الرمز — كل ذلك دون تشغيل متصفح واحد.

const CaptchaAI = require("./captchaai");
const axios = require("axios");
const cheerio = require("cheerio");

async function scrapeProtectedPage(url) {
  const solver = new CaptchaAI(process.env.CAPTCHAAI_API_KEY);

  // Step 1: Fetch the page
  const page = await axios.get(url);
  const $ = cheerio.load(page.data);

  // Step 2: Extract the reCAPTCHA site key
  const siteKey = $(".g-recaptcha").attr("data-sitekey");
  if (!siteKey) {
    console.log("No CAPTCHA found, returning page content");
    return page.data;
  }

  // Step 3: Solve the CAPTCHA
  console.log(`Solving CAPTCHA for ${url}...`);
  const token = await solver.solve({
    method: "userrecaptcha",
    googlekey: siteKey,
    pageurl: url,
  });

  // Step 4: Submit form with token
  const formAction = $("form").attr("action") || url;
  const formData = {};

  $("form input").each((_, el) => {
    const name = $(el).attr("name");
    const value = $(el).attr("value") || "";
    if (name) formData[name] = value;
  });
  formData["g-recaptcha-response"] = token;

  const result = await axios.post(formAction, new URLSearchParams(formData), {
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
  });

  return result.data;
}

scrapeProtectedPage("https://example.com/data")
  .then((data) => console.log("Success:", typeof data))
  .catch(console.error);

التشغيل المتزامن وعدد الخيوط

عندما تحتاج إلى حل عشرات المهام معاً، أرسلها جميعاً ثم انتظر نتائجها عبر Promise.all، مع تجميع الأخطاء بدل إيقاف الدفعة كلها عند أول فشل.

async function solveBatch(urls, siteKey) {
  const solver = new CaptchaAI(process.env.CAPTCHAAI_API_KEY);

  const promises = urls.map(async (url) => {
    try {
      const token = await solver.solve({
        method: "userrecaptcha",
        googlekey: siteKey,
        pageurl: url,
      });
      return { url, token, error: null };
    } catch (error) {
      return { url, token: null, error: error.message };
    }
  });

  const results = await Promise.all(promises);

  const solved = results.filter((r) => r.token);
  console.log(`Solved ${solved.length}/${urls.length}`);
  return results;
}

عدد الخيوط المتزامنة في خطتك هو ما يحدّد سقف المعالجة الآنية، لا عدد الحلول. تبدأ خطة BASIC بـ 5 خيوط مقابل 15 دولاراً شهرياً، وترتفع الخطط حتى VIP-3 بـ 5,000 خيط مقابل 7,500 دولار، مع حلول غير محدودة داخل كل خطة والفوترة على الخيط لا على الحل الواحد. اضبط حجم الدفعة في solveBatch بما يوافق حدّ خيوط خطتك حتى تتجنّب الطلبات المرفوضة عند تجاوز السقف.

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

الخطأ السبب الإصلاح
AxiosError: getaddrinfo ENOTFOUND مشكلة في DNS تحقق من اتصال الشبكة
Submit failed: ERROR_WRONG_USER_KEY مفتاح API غير صالح راجع المفتاح من لوحة التحكم
Submit failed: ERROR_ZERO_BALANCE الرصيد صفر أضف رصيداً إلى الحساب
رفض الموقع المستهدف للرمز انتهت صلاحية الرمز أرسل الرمز خلال 60 ثانية من استلامه

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

هل يحل CaptchaAI كل أنواع CAPTCHA عبر HTTP؟

تعالج الواجهة نفسها reCAPTCHA v2 وv3 (بما فيها Enterprise)، وCloudflare Turnstile وCloudflare Challenge، وGeeTest v3، وكابتشا الصور والشبكة، وBLS. أما hCaptcha وFunCaptcha (Arkose Labs) فغير مدعومَين حالياً، ودعم GeeTest v4 قادم قريباً وليس متاحاً بعد. وأنواع CaptchaFox وFriendly Captcha وLemin متاحة في مرحلة تجريبية (beta).

كم مهمة يمكن تشغيلها في وقت واحد؟

يحدّد عدد الخيوط المتزامنة في خطتك سقف المعالجة الآنية. مع خطة BASIC ($15 شهرياً، 5 خيوط) يمكن معالجة 5 مهام في آن واحد، والحلول غير محدودة داخل كل خطة. لرفع الإنتاجية، انقل الحمل إلى خطة أعلى بعدد خيوط أكبر واضبط حجم الدفعة في الكود تبعاً لذلك.

كيف أضبط مهلة الانتظار في الاستطلاع الدوري؟

المُعامل timeoutMs في التابع poll يحدّد أقصى مدة انتظار قبل رمي خطأ المهلة، وقيمته الافتراضية 300000 مللي ثانية (5 دقائق). خفّضه في المسارات الحساسة للزمن وارفعه للأنواع الأبطأ. الفاصل بين كل استطلاع وآخر مضبوط على 5 ثوانٍ داخل الحلقة.

هل يصلح هذا المسار لبيئات serverless؟

نعم. لأن الدورة كلها طلبات HTTP دون متصفح، يعمل الكود كما هو داخل AWS Lambda أو Azure Functions أو Google Cloud Functions ضمن حدود ذاكرة صغيرة. انتبه فقط إلى أن مهلة الدالة يجب أن تتجاوز قيمة timeoutMs حتى تكتمل دورة الحل قبل انتهاء التنفيذ.

أدلة ذات صلة

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