const express = require('express'); const puppeteer = require('puppeteer-extra'); const StealthPlugin = require('puppeteer-extra-plugin-stealth'); const randomUseragent = require('random-useragent'); const axios = require('axios'); const fs = require('fs'); const FormData = require('form-data'); puppeteer.use(StealthPlugin()); const app = express(); app.use(express.json()); // Enhanced random delay function const randomDelay = (min = 100, max = 300) => new Promise(resolve => setTimeout(resolve, Math.random() * (max - min) + min)); // Realistic mouse movement simulation const humanMouseMove = async (page, selector) => { const element = await page.$(selector); const box = await element.boundingBox(); // Simulate realistic mouse path await page.mouse.move( box.x + Math.random() * box.width, box.y + Math.random() * box.height, { steps: Math.floor(Math.random() * 10) + 5 } ); await randomDelay(50, 150); }; // Human-like typing with realistic patterns const humanType = async (page, selector, text, options = {}) => { await page.focus(selector); await randomDelay(100, 300); for (let i = 0; i < text.length; i++) { const char = text[i]; await page.keyboard.type(char); // Realistic typing delays let delay = Math.random() * 120 + 50; // Longer pauses for special characters if (['.', '@', '_', '-'].includes(char)) { delay += Math.random() * 100; } // Occasional longer pauses (thinking) if (Math.random() < 0.1) { delay += Math.random() * 400 + 200; } await new Promise(resolve => setTimeout(resolve, delay)); } }; // Random scrolling to simulate human behavior const humanScroll = async (page) => { const scrolls = Math.floor(Math.random() * 3) + 1; for (let i = 0; i < scrolls; i++) { const scrollDistance = Math.random() * 500 + 100; const direction = Math.random() > 0.5 ? 1 : -1; await page.evaluate((distance, dir) => { window.scrollBy(0, distance * dir); }, scrollDistance, direction); await randomDelay(500, 1500); } // Scroll back to top await page.evaluate(() => window.scrollTo(0, 0)); await randomDelay(300, 800); }; // Simulate random mouse movements const simulateHumanActivity = async (page) => { // Random mouse movements for (let i = 0; i < Math.random() * 5 + 2; i++) { await page.mouse.move( Math.random() * 1920, Math.random() * 1080, { steps: Math.floor(Math.random() * 20) + 10 } ); await randomDelay(200, 800); } // Random clicks in empty areas if (Math.random() > 0.7) { await page.mouse.click(Math.random() * 200 + 100, Math.random() * 200 + 100); await randomDelay(100, 300); } }; async function uploadToCatbox(filePath) { const form = new FormData(); form.append('reqtype', 'fileupload'); form.append('fileToUpload', fs.createReadStream(filePath)); const response = await axios.post('https://catbox.moe/user/api.php', form, { headers: form.getHeaders(), }); return response.data; } app.post('/login', async (req, res) => { const { email, password } = req.body; if (!email || !password) { return res.status(400).json({ error: 'Missing email or password' }); } let browser; try { // Enhanced browser launch options browser = await puppeteer.launch({ headless: true, defaultViewport: null, args: [ '--no-sandbox', '--disable-setuid-sandbox', '--disable-blink-features=AutomationControlled', '--disable-dev-shm-usage', '--disable-infobars', '--disable-extensions', '--disable-plugins', '--disable-images', '--disable-javascript-harmony-shipping', '--disable-background-timer-throttling', '--disable-backgrounding-occluded-windows', '--disable-renderer-backgrounding', '--disable-features=TranslateUI', '--disable-ipc-flooding-protection', '--disable-hang-monitor', '--disable-popup-blocking', '--disable-prompt-on-repost', '--disable-sync', '--disable-domain-reliability', '--disable-component-extensions-with-background-pages', '--no-default-browser-check', '--no-first-run', '--no-pings', '--password-store=basic', '--use-mock-keychain', '--disable-background-networking', '--disable-default-apps', '--disable-translate', '--disable-device-discovery-notifications', '--window-size=1920,1080', '--window-position=0,0', '--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36' ], ignoreDefaultArgs: ['--enable-automation'], ignoreHTTPSErrors: true, }); const page = await browser.newPage(); // Enhanced stealth configurations await page.evaluateOnNewDocument(() => { // Remove webdriver property Object.defineProperty(navigator, 'webdriver', { get: () => undefined, }); // Spoof navigator properties Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'], }); Object.defineProperty(navigator, 'plugins', { get: () => [ { 0: {type: "application/x-google-chrome-pdf", suffixes: "pdf", description: "Portable Document Format", enabledPlugin: "[object Plugin]"}, description: "Portable Document Format", filename: "internal-pdf-viewer", length: 1, name: "Chrome PDF Plugin" }, { 0: {type: "application/pdf", suffixes: "pdf", description: "", enabledPlugin: "[object Plugin]"}, description: "", filename: "mhjfbmdgcfjbbpaeojofohoefgiehjai", length: 1, name: "Chrome PDF Viewer" } ], }); Object.defineProperty(navigator, 'platform', { get: () => 'Win32', }); Object.defineProperty(navigator, 'hardwareConcurrency', { get: () => 8, }); Object.defineProperty(navigator, 'deviceMemory', { get: () => 8, }); // Spoof screen properties Object.defineProperty(screen, 'width', { get: () => 1920, }); Object.defineProperty(screen, 'height', { get: () => 1080, }); Object.defineProperty(screen, 'colorDepth', { get: () => 24, }); Object.defineProperty(screen, 'pixelDepth', { get: () => 24, }); // Override permissions const originalQuery = window.navigator.permissions.query; window.navigator.permissions.query = (parameters) => ( parameters.name === 'notifications' ? Promise.resolve({ state: Notification.permission }) : originalQuery(parameters) ); // Spoof timezone Date.prototype.getTimezoneOffset = function() { return -300; // EST timezone }; // Remove automation indicators delete navigator.__proto__.webdriver; // Mock chrome runtime window.chrome = { runtime: { onConnect: undefined, onMessage: undefined, connect: undefined, sendMessage: undefined, }, }; // Spoof canvas fingerprinting const getContext = HTMLCanvasElement.prototype.getContext; HTMLCanvasElement.prototype.getContext = function(a, b) { const context = getContext.call(this, a, b); if (a === '2d') { const originalIsPointInPath = context.isPointInPath; context.isPointInPath = function() { return originalIsPointInPath.apply(this, arguments); }; } return context; }; // Spoof WebGL fingerprinting const getParameter = WebGLRenderingContext.prototype.getParameter; WebGLRenderingContext.prototype.getParameter = function(parameter) { if (parameter === 37445) { return 'Intel Open Source Technology Center'; } if (parameter === 37446) { return 'Mesa DRI Intel(R) Ivybridge Mobile '; } return getParameter.call(this, parameter); }; }); // Set realistic viewport and user agent const userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36'; await page.setUserAgent(userAgent); await page.setViewport({ width: 1920, height: 1080, deviceScaleFactor: 1, hasTouch: false, isLandscape: true, isMobile: false, }); // Enhanced HTTP headers await page.setExtraHTTPHeaders({ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.9', 'Accept-Encoding': 'gzip, deflate, br', 'DNT': '1', 'Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1', 'Sec-Fetch-Dest': 'document', 'Sec-Fetch-Mode': 'navigate', 'Sec-Fetch-Site': 'none', 'Sec-Fetch-User': '?1', 'Cache-Control': 'max-age=0', }); // Request interception for performance await page.setRequestInterception(true); page.on('request', (req) => { const type = req.resourceType(); if (['image', 'stylesheet', 'font', 'media'].includes(type)) { req.abort(); } else { req.continue(); } }); console.log('🌐 Navigating to login page...'); await page.goto('https://sso.crunchyroll.com/login', { waitUntil: 'networkidle2', timeout: 60000, }); // Wait and simulate human behavior await randomDelay(2000, 4000); await simulateHumanActivity(page); await humanScroll(page); // Wait for form elements with better error handling try { await page.waitForSelector('input[name="email"]', { timeout: 30000 }); console.log('📧 Email input found'); } catch (error) { console.log('❌ Email input not found, trying alternative selectors'); await page.waitForSelector('input[type="email"], #email, [placeholder*="email" i]', { timeout: 30000 }); } // Simulate human-like interaction with email field await humanMouseMove(page, 'input[name="email"]'); await page.click('input[name="email"]'); await randomDelay(500, 1200); // Clear field first (in case there's placeholder text) await page.keyboard.down('Control'); await page.keyboard.press('a'); await page.keyboard.up('Control'); await page.keyboard.press('Backspace'); await randomDelay(200, 500); await humanType(page, 'input[name="email"]', email); console.log('✅ Email entered'); await randomDelay(800, 1500); // Similar approach for password try { await page.waitForSelector('input[name="password"]', { timeout: 10000 }); } catch (error) { await page.waitForSelector('input[type="password"], #password, [placeholder*="password" i]', { timeout: 30000 }); } await humanMouseMove(page, 'input[name="password"]'); await page.click('input[name="password"]'); await randomDelay(300, 800); await humanType(page, 'input[name="password"]', password); console.log('🔒 Password entered'); // Random delay before clicking login await randomDelay(1000, 2500); await simulateHumanActivity(page); // Find and interact with login button let loginButton; try { await page.waitForSelector('button[data-t="login-button"]', { visible: true, timeout: 10000 }); loginButton = 'button[data-t="login-button"]'; } catch (error) { // Try alternative selectors const buttonSelectors = [ 'button[type="submit"]', 'input[type="submit"]', 'button:contains("Log in")', 'button:contains("Sign in")', '[role="button"]:contains("Log")', '.login-button', '#login-button' ]; for (const selector of buttonSelectors) { try { await page.waitForSelector(selector, { visible: true, timeout: 2000 }); loginButton = selector; break; } catch (e) { continue; } } } if (!loginButton) { throw new Error('Login button not found'); } // Screenshot before clicking login const beforePath = './before-login.png'; await page.screenshot({ path: beforePath, fullPage: true }); const beforeUrl = await uploadToCatbox(beforePath); console.log('🟡 Before login screenshot uploaded:', beforeUrl); // Human-like button interaction await humanMouseMove(page, loginButton); await randomDelay(200, 500); // Sometimes hover before clicking if (Math.random() > 0.5) { await page.hover(loginButton); await randomDelay(100, 300); } await page.click(loginButton); console.log('🔄 Login button clicked'); // Wait for navigation or response try { await Promise.race([ page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 45000 }), page.waitForSelector('.error, [class*="error"], [id*="error"]', { timeout: 30000 }) .then(() => { throw new Error('Login error detected'); }), new Promise(resolve => setTimeout(resolve, 40000)) // Fallback timeout ]); } catch (navError) { console.log('⚠️ Navigation wait completed with potential issues'); } // Additional wait for any dynamic content await randomDelay(3000, 6000); // Screenshot after login attempt const afterPath = './after-login.png'; await page.screenshot({ path: afterPath, fullPage: true }); const afterUrl = await uploadToCatbox(afterPath); console.log('🟢 After login screenshot uploaded:', afterUrl); const currentUrl = page.url(); const loginSuccess = !currentUrl.includes('/login') && !currentUrl.includes('sso.crunchyroll.com'); // Additional success indicators const hasAuthCookie = (await page.cookies()).some(cookie => cookie.name.toLowerCase().includes('auth') || cookie.name.toLowerCase().includes('session') || cookie.name.toLowerCase().includes('token') ); console.log(`🎯 Login Result: ${loginSuccess ? 'SUCCESS' : 'FAILED'}`); console.log(`📍 Current URL: ${currentUrl}`); console.log(`🍪 Auth cookies present: ${hasAuthCookie}`); res.json({ success: loginSuccess, currentUrl: currentUrl, userAgent: userAgent, hasAuthCookie: hasAuthCookie, screenshots: { before: beforeUrl, after: afterUrl }, timestamp: new Date().toISOString() }); } catch (err) { console.error('❌ Error during login:', err); res.status(500).json({ error: 'Login failed', details: err.message, timestamp: new Date().toISOString() }); } finally { if (browser) { await browser.close(); } } }); const PORT = process.env.PORT || 7860; app.listen(PORT, () => { console.log(`🚀 Enhanced Anti-Detection Server running on port ${PORT}`); console.log(`🛡️ Stealth features enabled: Human typing, mouse movement, scrolling, fingerprint spoofing`); });