أدلة

كيف تكشف المتصفحات بلا واجهة والأتمتة في صفحة التسجيل

إشارات المتصفح التي تفضح التسجيلات عبر Puppeteer وPlaywright وSelenium، ولماذا يمكن تزييف كل منها وحدها، وكيف تجمعها دون حظر أشخاص حقيقيين.

قراءة 9 دقائق · آخر تحديث 2026-10-31 · Attrelix

لماذا تستخدم البوتات الآن متصفحات حقيقية

قبل بضع سنوات كانت معظم بوتات التسجيل سكربتات HTTP بسيطة ترسل نموذجك مباشرة. هذه سهلة الإيقاف: لا تشغّل JavaScript، فلا يصل شيء مما تحسبه صفحتك في المتصفح. اليوم تتحكم معظم البوتات الجادة في متصفح حقيقي عبر Puppeteer أو Playwright أو Selenium، غالبًا بلا واجهة، وأحيانًا عبر متصفح مضاد للكشف يموّه بصمته. إنها تشغّل JavaScript الخاص بك، وتعرض صفحتك، وتملأ النموذج كما يفعل الإنسان.

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

الإشارة 1: علامة WebDriver

المتصفحات الخاضعة لأتمتة من نوع WebDriver تضبط navigator.webdriver على true. هذا جزء مقصود من معيار WebDriver، وتكشفه الإعدادات الافتراضية في Selenium وPuppeteer وPlaywright.

const automated = navigator.webdriver === true;

إضافات «stealth» تحذفها أو تستبدلها، لذا فغيابها لا يثبت شيئًا. أما وجودها فشبه قاطع: المستخدمون الحقيقيون لا يملكونها تقريبًا أبدًا.

الإشارة 2: وكيل المستخدم بلا واجهة

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

الإشارة 3: عميل بروتوكول DevTools متصل

يتحكم Puppeteer وPlaywright في Chrome عبر بروتوكول DevTools. عندما يستمع عميل البروتوكول إلى أحداث وحدة التحكم، فإن تسجيل كائن يدفع المتصفح إلى تسلسله — بل وقراءة خصائص لا تلمسها الصفحة العادية أبدًا. دالة getter تسجل ما إذا قُرئت طريقة معروفة لملاحظة ذلك:

function devtoolsProtocolAttached() {
  let read = false;
  const e = new Error();
  Object.defineProperty(e, "stack", { get() { read = true; return ""; } });
  console.debug(e);
  return read;
}

تنطلق أيضًا عندما يفتح مطوّر أدوات DevTools، لذا امنحها وزنًا متوسطًا بدل اعتبارها حكمًا.

الإشارة 4: العرض البرمجي والنوافذ الغريبة

المتصفحات بلا واجهة على الخوادم لا تملك GPU، فيلجأ WebGL إلى عارض برمجي مثل SwiftShader أو llvmpipe. يمكنك قراءة اسم العارض عبر الامتداد WEBGL_debug_renderer_info عندما يتيحه المتصفح. بعض إعدادات التشغيل بلا واجهة تعلن أيضًا نافذة عرضها أو ارتفاعها صفر. الأجهزة الافتراضية وسطح المكتب البعيد تشترك في هذه الصفات، لذا فهي إشارات ضعيفة بمفردها.

الإشارة 5: بصمة تناقض نفسها

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

  • نظام التشغيل في وكيل المستخدم مقابل navigator.platform وUser-Agent Client Hints.
  • عائلة المتصفح في وكيل المستخدم مقابل ميزات لا يملكها إلا ذلك المحرك.
  • الخطوط المثبتة مقابل الخطوط التي تأتي مع نظام التشغيل ذاك.
  • لوحة canvas تُرسم مرتين متتاليتين فتنتج صورتين مختلفتين — علامة على ضجيج مُحقَن.
  • Notification.permission تقول «denied» بينما تقول Permissions API «prompt».

كل تناقض ضعيف بمفرده، لأن إضافات الخصوصية والإعدادات غير المألوفة تنتج بعضها. اثنان أو ثلاثة معًا نمط قوي.

الإشارة 6: الرمز الذي لم يعد

تقنية بسيطة ومتينة: اجعل سكربت صفحة التسجيل يطلب رمزًا قصير العمر يُستخدم مرة واحدة، وضعه في حقل مخفي في النموذج، وتحقق منه على الخادم. البوت الذي يتخطى JavaScript الخاص بك يصل بلا رمز صالح؛ والذي يعيد استخدام رمز قديم يصل برمز مستعمَل. لا تحتاج إلى معرفة كيف يعمل البوت لتلاحظ أنه لم يشغّل صفحتك فعلًا. اجعل الرمز لاستخدام واحد، ومرتبطًا بموقعك، وينتهي خلال دقائق.

الإشارة 7: السلوك لا البصمة

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

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

تنبيه بشأن الإشارة 3: في Chrome الحالي لا تنطلق حيلة DevTools إلا عندما يشترك عميل الأتمتة في أحداث وحدة التحكم، لذا اعتبرها إضافة لا الكاشف الأساسي.

اجمع الإشارات ولا تحظر بإشارة واحدة

عامل كل إشارة كنقاط في درجة واحدة وقرّر بناءً على المجموع. ترجيح معقول للبدء، من الأقوى إلى الأضعف:

الإشارةالوزنالسبب
navigator.webdriver بقيمة trueمرتفعلا يكون true تقريبًا لدى المستخدمين الحقيقيين
وكيل مستخدم HeadlessChromeمرتفعلا ترسله إلا الإصدارات بلا واجهة
رمز مفقود أو مُعاد استخدامهمرتفعلم يعمل سكربت الصفحة، أو عمل مرة لتسجيلات كثيرة
بروتوكول DevTools متصلمتوسطيطلقه أيضًا المطورون الذين يفتحون DevTools
تناقضات نظام التشغيل أو المتصفحمتوسطاستبدالات مضادة للكشف، لكن بعض الإضافات أيضًا
عارض برمجي، نافذة بحجم صفرمنخفضتشترك فيها الأجهزة الافتراضية وسطح المكتب البعيد

اجمع إشارات المتصفح مع إشارات الخادم — تسجيلات من نطاقات IP سحابية، ودفعات من شبكة فرعية واحدة، وحسابات مرتبطة بالجهاز نفسه — ولن يبدو نظيفًا في جميعها معًا إلا عدد قليل جدًا من البوتات.

ما لا ينبغي فعله

  • لا تحظر لمجرد غياب الإضافات أو اللغات. المتصفحات المعززة للخصوصية تزيلها.
  • لا تنشر منطق الكشف في صورة فحوص بأسماء واضحة يستطيع المشغّل البحث عنها وتجاوزها دفعة واحدة؛ اجمع الحقائق الخام في المتصفح واتخذ القرار على الخادم.
  • لا تثق ثقة عمياء بأي شيء يعلنه المتصفح. العميل تحت سيطرة البوت. التحقق يجري على خادمك، بسرّك أنت.

كيف يفعل Attrelix ذلك

يجمع وكيل Attrelix حقائق المتصفح هذه ورمز زائر لاستخدام واحد في صفحة التسجيل لديك؛ ويجمعها الخادم مع إشارات الشبكة وصندوق البريد والحسابات المرتبطة في درجة واحدة. كل الأوزان منشورة علنًا في التوثيق، ولا يمكن لإشارة ضعيفة واحدة وحدها أن تحيل تسجيلًا إلى المراجعة.

الخلاصة

  • البوتات الحديثة تستخدم متصفحات حقيقية؛ ابحث عن مواضع اختلاف الأتمتة عن الإنسان.
  • WebDriver ووكيل المستخدم بلا واجهة والرموز المفقودة إشارات قوية؛ والباقي ضعيف لكنه يتراكم.
  • قرّر على الخادم بناءً على درجة، لا بناءً على علامة واحدة من المتصفح.

أدلة أخرى