Skip to content

"--bot-script" like support? #123

@Mahkhmood8

Description

@Mahkhmood8

I found this on the web

https://github.com/botswin/BotBrowser/blob/main/examples/bot-script/cloudflare-turnstile.js

Image

Its sound very interesting, btw upon cloudflare detection , it clicks,

Activity

Mahkhmood8

Mahkhmood8 commented on Oct 18, 2025

@Mahkhmood8
Author

I MANAGED TO GET IT WORKING !!!!
usage

//   [do it after browser.newPage]  const page = await this.browser.newPage();

    const automation = new TurnstileAutomation(page);
    await automation.initialize();

const CLOUDFLARE_CHALLENGE_URL = 'challenges.cloudflare.com/cdn-cgi/challenge-platform';
const MONITORING_INTERVAL = 2000;
const CLICK_X = 30;
const CLICK_Y = 30;

class TurnstileAutomation {
    constructor(page) {
        this.page = page;
        this.browser = null;
        this.monitoringActive = true;
        this.activeTargets = new Set();
        this.targetFrameFound = false;
    }

    async initialize() {
        console.log("BotBrowser Frame Automation Script loaded!");
        
        // Get browser instance
        this.browser = this.page.browser();
        console.log("Browser instance obtained!");

        // Start monitoring
        this.startFrameMonitoring();
    }

    startFrameMonitoring() {
        console.log(`Starting frame monitoring for ${CLOUDFLARE_CHALLENGE_URL}`);

        const monitor = async () => {
            while (this.monitoringActive) {
                try {
                    // Get all targets using browser CDP
                    const targets = await this.browser.targets();
                    console.log(`Found ${targets.length} targets`);

                    // Process each target
                    for (const target of targets) {
                        const type = target.type();
                        const url = target.url();
                        
                        if (type === 'page') {
                            console.log("Found page target:", target._targetId, "URL:", url);
                            await this.attachToTarget(target);
                        } else if (type === 'iframe') {
                            console.log("Found iframe target:", target._targetId, "URL:", url);
                            await this.attachToTarget(target);
                        } else if (type === 'other' && url && url.includes('challenges.cloudflare.com')) {
                            console.log("Found Cloudflare challenge target:", type, target._targetId, "URL:", url);
                            await this.attachToTarget(target);
                        } else {
                            console.log("Found other target:", type, target._targetId, "URL:", url);
                        }
                    }
                } catch (error) {
                    console.error("Error during monitoring:", error.message);
                }

                await this.sleep(MONITORING_INTERVAL);
            }
        };

        monitor().catch(err => console.error("Monitoring loop error:", err));
    }

    async attachToTarget(target) {
        const targetId = target._targetId;
        const url = target.url();
        
        console.log("Attempting to process target:", targetId, "URL:", url);

        // Skip if already processing
        if (this.activeTargets.has(targetId)) {
            console.log("Target currently being processed, skipping:", targetId);
            return;
        }

        // Check if Cloudflare challenge
        const isCloudflareChallenge = url.includes(CLOUDFLARE_CHALLENGE_URL);
        if (!isCloudflareChallenge) {
            console.log("Not a Cloudflare challenge frame, skipping:", url);
            return;
        }

        console.log("Found Cloudflare challenge frame:", url);
        this.activeTargets.add(targetId);

        try {
            // Get CDP session for this target
            let cdpSession;
            
            // Try to get existing page or create session
            if (target.type() === 'page') {
                const page = await target.page();
                if (page) {
                    cdpSession = await page._client();
                    console.log("Got CDP session from page");
                }
            } else {
                // For iframe/other, need to create new CDP session
                const browserClient = await this.page._client();
                const result = await browserClient.send('Target.attachToTarget', {
                    targetId: targetId,
                    flatten: true
                });
                console.log("Created new CDP session:", result.sessionId);
                
                // Try different ways to access the session
                let connection = browserClient.connection?.() || browserClient.connection || browserClient._connection;
                
                if (!connection) {
                    console.log("Trying to get connection from browser client properties...");
                    console.log("Available properties:", Object.keys(browserClient));
                }
                
                // The session should be in the connection's sessions map
                cdpSession = connection?.sessions?.get(result.sessionId) || 
                             connection?._sessions?.get(result.sessionId) ||
                             connection?._sessionMap?.get(result.sessionId);
                
                if (!cdpSession) {
                    // Fallback: create a simple wrapper that uses the browser client
                    console.log("Using fallback session wrapper");
                    cdpSession = {
                        _sessionId: result.sessionId,
                        _browserClient: browserClient,
                        send: async function(method, params = {}) {
                            console.log(`Sending command: ${method}`, params);
                            // Don't use sendMessageToTarget with flatten=true
                            // Instead, send directly - the sessionId is handled internally
                            try {
                                return await this._browserClient.send(method, params);
                            } catch (error) {
                                console.error(`Error sending ${method}:`, error.message);
                                throw error;
                            }
                        }
                    };
                }
                
                console.log("Got CDP session object");
            }

            console.log("Successfully attached to target:", targetId);

            // Enable Runtime
            await cdpSession.send('Runtime.enable');
            console.log("Runtime enabled for target:", targetId);

            // Setup mobile emulation
            await this.setupMobileEmulation(targetId, cdpSession);

            // Perform click
            await this.sleep(500);
            await this.performDirectClick(targetId, cdpSession);

        } catch (error) {
            console.error("Failed to attach to target:", targetId, error.message, error.stack);
            this.activeTargets.delete(targetId);
        }
    }

    async setupMobileEmulation(targetId, cdpSession) {
        try {
            const result = await cdpSession.send('Runtime.evaluate', {
                expression: `
                    (() => {
                        const mobileUserAgent = /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
                        const hasTouchSupport = ('ontouchstart' in window);
                        
                        return {
                            isMobile: mobileUserAgent,
                            userAgent: navigator.userAgent,
                            innerWidth: window.innerWidth,
                            touchSupport: hasTouchSupport,
                            maxTouchPoints: navigator.maxTouchPoints
                        };
                    })()
                `,
                returnByValue: true
            });

            if (result && result.result && result.result.value) {
                const deviceInfo = result.result.value;
                console.log("Device detection:", deviceInfo);

                if (deviceInfo.isMobile) {
                    console.log("Mobile device detected, enabling touch events");
                    await cdpSession.send('Emulation.setEmitTouchEventsForMouse', {
                        enabled: true,
                        configuration: 'mobile'
                    });
                    console.log("Mobile touch events enabled for target:", targetId);
                } else {
                    console.log("Desktop device detected, using standard mouse events");
                }
            }
        } catch (error) {
            console.log("Could not detect device type, defaulting to desktop mode:", error.message);
        }
    }

    async performDirectClick(targetId, cdpSession) {
        console.log("Performing direct coordinate click on target:", targetId);
        console.log(`Clicking directly at coordinates: ${CLICK_X}, ${CLICK_Y}`);
        
        await this.performMouseClick(targetId, cdpSession, CLICK_X, CLICK_Y);
    }

    async performMouseClick(targetId, cdpSession, x, y) {
        console.log("Performing mouse click at coordinates:", x, y);

        try {
            // Mouse press
            await cdpSession.send('Input.dispatchMouseEvent', {
                type: 'mousePressed',
                x: x,
                y: y,
                button: 'left',
                clickCount: 1
            });

            console.log("Mouse pressed at:", x, y);

            await this.sleep(100);

            // Mouse release
            await cdpSession.send('Input.dispatchMouseEvent', {
                type: 'mouseReleased',
                x: x,
                y: y,
                button: 'left',
                clickCount: 1
            });

            console.log("Mouse released. Click completed successfully!");
            console.log("Turnstile automation completed for this target!");

            this.activeTargets.delete(targetId);
            this.targetFrameFound = true;

            console.log("Continuing to monitor for new Turnstile challenges...");

        } catch (error) {
            console.error("Mouse event failed:", error.message, error.stack);
            this.activeTargets.delete(targetId);
        }
    }

    async sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    getAutomationStatus() {
        return {
            monitoring: this.monitoringActive,
            targetFound: this.targetFrameFound,
            timestamp: new Date().toISOString(),
            activeTargets: Array.from(this.activeTargets)
        };
    }

    stop() {
        console.log("Stopping Turnstile automation...");
        this.monitoringActive = false;
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @Mahkhmood8

        Issue actions

          "--bot-script" like support? · Issue #123 · rebrowser/rebrowser-patches