Puppeteer डिटेक्शन असल में कैसे काम करता है: 12 सिग्नल जो बॉट्स को पकड़वा देते हैं
ऑटोमेशन फ़्रेमवर्क असली ब्राउज़र का फ़िंगरप्रिंट अपनाते हैं, पर दर्जनों तरीक़ों से उसे बदल देते हैं। Puppeteer और Playwright पकड़ने के लिए डिफ़ेंडर जिन 12 JavaScript, नेटवर्क और बिहेवियरल सिग्नल्स का उपयोग करते हैं, उनकी फ़ील्ड गाइड।
ऑटोमेशन फ़्रेमवर्क असली ब्राउज़र को नियंत्रित करते हैं, जिसका मतलब है कि वे ब्राउज़र का फ़िंगरप्रिंट अपना लेते हैं। Puppeteer से चलने वाले Chrome का user agent, Chrome वर्शन और Chromium build वही होता है जो किसी इंसान के Chrome का। ऊपरी तौर पर वे एक जैसे दिखते हैं।
लेकिन ऑटोमेशन फ़्रेमवर्क ब्राउज़र को दर्जनों सूक्ष्म तरीक़ों से बदल देते हैं — जिनमें से ज़्यादातर JavaScript से देखे जा सकते हैं। डिटेक्शन कोई जादू नहीं है। यह एक चेकलिस्ट है।
1. navigator.webdriver फ़्लैग
सबसे सरल और सबसे मशहूर सिग्नल। जब Chrome किसी ऑटोमेशन फ़्रेमवर्क के तहत चलता है, तो navigator.webdriver true लौटाता है। यह W3C WebDriver स्पेसिफ़िकेशन का हिस्सा है और Chromium इसे डिफ़ॉल्ट रूप से लागू करता है।
हर गंभीर ऑटोमेशन प्रोजेक्ट इसे कुछ ही सेकंड में पैच कर देता है। Puppeteer-extra-stealth getter को ओवरराइड कर देता है। Playwright यूज़र नए डॉक्यूमेंट्स पर Object.defineProperty स्क्रिप्ट इंजेक्ट करते हैं। इस फ़्लैग को छिपाना बेहद आसान है।
लेकिन इसे इतनी आसानी से छिपाया जा सकना ही ख़ुद एक सिग्नल है। एक वैध Chrome को कुछ भी छिपाने की ज़रूरत नहीं होती। जब कोई पेज Object.getOwnPropertyDescriptor(Navigator.prototype, 'webdriver') की जाँच करता है और descriptor किसी नेटिव ब्राउज़र से अलग दिखता है — तो फ़्लैग पैच होने के बाद भी ऑटोमेशन पकड़ी जाती है।
2. chrome object की विसंगति
वैध Chrome एक ग्लोबल window.chrome object उजागर करता है जिसमें काफ़ी संरचना होती है — chrome.runtime, chrome.loadTimes, chrome.csi। Headless Chrome और पुराने Puppeteer सेटअप या तो इस object को पूरी तरह छोड़ देते हैं या इसका कटा-छँटा वर्शन दिखाते हैं।
Stealth plugins इस object को दोबारा बनाते हैं, पर यह पुनर्निर्माण अधूरा होता है। chrome.runtime.onConnect मौजूद हो सकता है पर chrome.runtime.PlatformOs के बिना। फ़ंक्शन सिग्नेचर undefined के बजाय objects लौटा सकते हैं। हर मिसमैच एक पॉज़िटिव सिग्नल है।
3. Permissions API में असंगतियाँ
असली ब्राउज़र Permissions API से क्वेरी किए जाने पर सुसंगत नतीजे लौटाते हैं। navigator.permissions.query({name: 'notifications'}) को 'default' लौटाना चाहिए अगर यूज़र ने स्पष्ट रूप से अनुमति न दी हो और न ही मना किया हो।
Headless Chrome डिफ़ॉल्ट रूप से 'denied' लौटाता है, क्योंकि अनुमति का प्रॉम्प्ट दिखाने के लिए कोई UI नहीं होता। ऑटोमेशन फ़्रेमवर्क इसे पैच करते हैं — पर अक्सर ग़लत तरीक़े से। एक आम पहचान: 'clipboard-read' जैसी असामान्य अनुमति को क्वेरी करने पर ऐसा नतीजा मिलता है जो मौजूदा वर्शन में असली Chrome के व्यवहार से मेल नहीं खाता।
4. Plugin और MIME type ऐरे
असली ब्राउज़र में navigator.plugins एक PluginArray लौटाता है जिसमें PDF viewer और Chromium PDF plugin जैसी एंट्रीज़ होती हैं। Headless मोड में यह ऐरे ख़ाली होता है।
Stealth plugins नक़ली एंट्रीज़ जोड़ते हैं, पर इन एंट्रीज़ में अक्सर ग़लत properties होती हैं — गायब length, ग़लत description फ़ील्ड, या ऐसे plugin objects जो instanceof से जाँचने पर Plugin instances की तरह व्यवहार नहीं करते।
5. भाषा और लोकेल का मिसमैच
navigator.language और navigator.languages को Accept-Language HTTP हेडर से मेल खाना चाहिए। इन्हें Intl.DateTimeFormat().resolvedOptions().timeZone द्वारा रिपोर्ट किए गए टाइमज़ोन के साथ भी सुसंगत होना चाहिए।
एक बॉट जो ख़ुद को Kyiv में होने का दावा करता है (Europe/Kyiv टाइमज़ोन) पर Accept-Language: en-US,en;q=0.9 भेजता है और navigator.language === 'en-US' रिपोर्ट करता है, संभव तो है पर सांख्यिकीय रूप से असामान्य है। जब इसे Frankfurt के किसी डेटासेंटर के IP के साथ जोड़ा जाता है, तो तस्वीर साफ़ हो जाती है।
6. WebGL renderer स्ट्रिंग्स
WebGL2RenderingContext.getParameter(WebGLDebugRendererInfo.UNMASKED_RENDERER_WEBGL) GPU वेंडर और मॉडल लौटाता है। किसी असली मशीन पर यह ऐसा हो सकता है:
ANGLE (Intel, Intel(R) UHD Graphics 620 Direct3D11 vs_5_0 ps_5_0)
किसी कंटेनर में चलने वाला Headless Chrome अक्सर ऐसा लौटाता है:
ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device (Subzero)), SwiftShader driver)
SwiftShader या Subzero वाली कोई भी GPU स्ट्रिंग एक मज़बूत बॉट सिग्नल है।
7. स्क्रीन और viewport की विसंगतियाँ
एक असली ब्राउज़र विंडो में window.outerWidth और window.outerHeight होते हैं जो ब्राउज़र क्रोम — एड्रेस बार, टैब, बुकमार्क बार — का हिसाब रखते हैं। outer और inner डाइमेंशन के बीच का अंतर आम तौर पर लंबवत रूप से 80–140 पिक्सेल होता है।
Headless ब्राउज़र में अक्सर outerHeight === innerHeight होता है क्योंकि दिखाने के लिए कोई क्रोम नहीं होता। Puppeteer में headless: false इसे ठीक कर देता है, पर कई ऑटोमेशन सेटअप अब भी बराबर डाइमेंशन के साथ चलते हैं।
8. फ़ॉन्ट एन्यूमरेशन
असली यूज़र के पास सैकड़ों इंस्टॉल किए गए फ़ॉन्ट होते हैं, जो OS, भाषा और इंस्टॉल किए गए ऐप्लिकेशन के हिसाब से भिन्न होते हैं। Office इंस्टॉल किए हुए Windows 11 में 500+ फ़ॉन्ट होते हैं। Alpine Linux चलाने वाले ऑटोमेशन कंटेनर में 30 होते हैं।
document.fonts.check() या offscreen canvas रेंडरिंग के ज़रिए फ़ॉन्ट एन्यूमरेशन इसे तुरंत उजागर कर देता है। एक ब्राउज़र जो ख़ुद को Windows 11 Chrome बताता है पर केवल 30 फ़ॉन्ट उजागर करता है, लगभग निश्चित रूप से ऑटोमेशन है।
9. माउस मूवमेंट एंट्रॉपी
असली यूज़र माउस को झटकों के साथ हिलाते हैं। वक्र रैखिक नहीं होते। गति बदलती रहती है। दो क्लिक के बीच आम तौर पर सैकड़ों mousemove इवेंट होते हैं।
ऑटोमेशन फ़्रेमवर्क मूवमेंट को कृत्रिम रूप से बनाते हैं — या तो निर्देशांकों तक सीधी रेखाओं से, या प्रोग्राम किए गए वक्रों से जिनमें इंसानी हाथ के सूक्ष्म कंपन नहीं होते। यहाँ तक कि Bezier-curve सिमुलेशन में भी संदिग्ध रूप से चिकने त्वरण प्रोफ़ाइल होते हैं।
बॉट डिटेक्शन सिस्टम मूवमेंट ट्रेस इकट्ठा करते हैं और उन्हें इंसानी गति के मॉडल के मुक़ाबले स्कोर करते हैं। बहुत अधिक सुसंगत वेग, बहुत साफ़ वक्र, या गायब माइक्रोइवेंट वाले ट्रेस फ़्लैग कर दिए जाते हैं।
10. टाइमिंग सिग्नेचर
ऑटोमेशन फ़्रेमवर्क JavaScript को यूज़र-चालित ब्राउज़र से अलग टाइमिंग विशेषताओं के साथ निष्पादित करते हैं। इवेंट्स के बीच performance.now() टाइमिंग, ख़ासकर pointerdown और pointerup के बीच, एक अलग वितरण का पालन करती है।
असली क्लिक होल्ड समय उच्च विचरण के साथ 50–150ms होते हैं। Puppeteer का डिफ़ॉल्ट क्लिक होल्ड एक निश्चित मान होता है — अक्सर 30ms या 100ms — जिसमें लगभग कोई विचरण नहीं होता। समान होल्ड समय वाले सौ क्लिक निर्णायक रूप से ऑटोमेशन हैं।
11. TLS फ़िंगरप्रिंट मिसमैच
यह वाला JavaScript को पूरी तरह बायपास कर देता है। जब Puppeteer कनेक्ट होता है, तो यह Chromium के TLS स्टैक का उपयोग करता है — असली Chrome के जैसा ही। पर undici-आधारित या axios-आधारित स्क्रेपर जो user agent स्पूफ़िंग के ज़रिए Chrome होने का नाटक करते हैं, वे Node.js के TLS स्टैक का उपयोग करते हैं, जिसका Client Hello सिग्नेचर (JA4 hash) स्पष्ट रूप से अलग होता है।
एक रिक्वेस्ट जो User-Agent: Chrome/124.0.6367.60 का दावा करती है पर Node.js का TLS फ़िंगरप्रिंट प्रस्तुत करती है, वह तुरंत ही किसी नॉन-ब्राउज़र क्लाइंट की पुष्टि है।
12. CDP प्रोटोकॉल लीकेज
Puppeteer और Playwright Chrome DevTools Protocol के ज़रिए Chrome से संवाद करते हैं। कुछ कॉन्फ़िगरेशन में यह प्रोटोकॉल पता लगाने योग्य अवशेष छोड़ जाता है — Runtime object पर अतिरिक्त properties, बदले हुए Error.stack फ़ॉर्मेट, या विशिष्ट console.debug आउटपुट जो केवल तभी दिखते हैं जब कोई CDP क्लाइंट अटैच होता है।
ख़ासकर Runtime.enable कमांड यह बदल देता है कि stack traces कैसे रेंडर होते हैं। जो बॉट कभी errors ट्रिगर नहीं करते, वे इस सिग्नल से बच जाते हैं, पर कोई भी ऑटोमेशन फ़्लो जो किसी exception से टकराता है (और ज़्यादातर टकराते हैं) फ़िंगरप्रिंट छोड़ जाता है।
इन सिग्नलों की लेयरिंग
कोई एक अकेला सिग्नल ऑटोमेशन का प्रमाण नहीं है। असामान्य GPU ड्राइवर वाला कोई असली यूज़र एक अजीब WebGL स्ट्रिंग लौटा सकता है। प्राइवेसी के प्रति सजग कोई यूज़र navigator.plugins को बदल चुका हो सकता है।
आधुनिक डिटेक्शन की ताक़त सिग्नलों को जोड़ने से आती है — 12 कमज़ोर पॉज़िटिव एक मज़बूत पॉज़िटिव से ज़्यादा ताक़तवर हैं, क्योंकि एक असली यूज़र शायद ही कभी एक साथ 2–3 से ज़्यादा विसंगतियाँ ट्रिगर करता है।
डिटेक्शन सिस्टम हर सिग्नल को एक वेट देते हैं और एक स्कोर की गणना करते हैं। थ्रेशोल्ड से ऊपर होने पर विज़िटर को ऑटोमेशन माना जाता है। सही थ्रेशोल्ड और वेट तय करना सबसे मुश्किल हिस्सा है — बहुत सख़्त हो तो वैध यूज़र ब्लॉक हो जाते हैं; बहुत ढीला हो तो परिष्कृत बॉट फिसल निकलते हैं।
सिग्नल ख़ुद आसान हिस्सा हैं। लगभग हर ऑटोमेशन फ़्रेमवर्क सभी 12 लीक करता है। असली इंजीनियरिंग यह तय करने में है कि कौन-से संयोजन मायने रखते हैं, कौन-से false positives हैं, और ऑटोमेशन फ़्रेमवर्क के अनुकूलित होने पर मॉडल को कैसे अपडेट किया जाए।