Bypassing Cloudflare Challenge with Puppeteer and 2Captcha

Bypassing Cloudflare Challenge with Puppeteer and 2captcha API

2captcha.com is bypass Cloudflare captcha service.

At first, the process of bypassing the Cloudflare protection can look quite complicated, but when you start writing the code it's much easier then appears.

First of all, you should clearly understand what's the difference between standalone Turnstile CAPTCHA and Cloudflare Challenge page.

Challenge Page Turnstile Captcha
You DO NOT see the original website You see the original website
You can locate Ray ID parameter on the page The page does not contain the Ray ID value
You can find a definition of _cf_chl_opt variable in the page source The _cf_chl_opt variable is undefined
Cloudflare Challenge Page Screenshot

For challenge pages there are some additional requirements: you have to intercept few additional values: chlPageData, cData, action, you have to use a modern User-Agent value, and we return you the value used.

How to bypass the Challenge Page

First of all we install the required dependencies: puppeteer and @2captcha/captcha-solver from npm.

yarn add @2captcha/captcha-solver

Start the browser

Nothing special, just starting the browswer with the default configuration.

const browser = await launch({
    headless: false,
    devtools: true
})

const [page] = await browser.pages()

Intercept the parameters

To do so, we inject a script that redefines turnstile.render, intercepts the parameters and logs them to console. We also redefine console.clear as Cloudflare calls it to clear the console output.

const preloadFile = readFileSync('./inject.js', 'utf8')
await page.evaluateOnNewDocument(preloadFile)
inject.js file content
console.clear = () => console.log('Console was cleared')
const i = setInterval(() => {
    if (window.turnstile) {
        clearInterval(i)
        window.turnstile.render = (a, b) => {
            let params = {
                sitekey: b.sitekey,
                pageurl: window.location.href,
                data: b.cData,
                pagedata: b.chlPageData,
                action: b.action,
                userAgent: navigator.userAgent,
                json: 1
            }
            console.log('intercepted-params:' + JSON.stringify(params))
            window.cfCallback = b.callback
            return
        }
    }
}, 50)

Solve the captcha with 2Captcha API

We catch the parameters using a handler for console events and use @2captcha/captcha-solver to solve the captcha with the API. Once we receive the token, we pass it to the callback function globally defined by our injected script. Once we defined our handler, we navigate to the target page.

page.on('console', async (msg) => {
    const txt = msg.text()
    if (txt.includes('intercepted-params:')) {
        const params = JSON.parse(txt.replace('intercepted-params:', ''))
        console.log(params)

        try {
            console.log(`Solving the captcha...`)
            const res = await solver.cloudflareTurnstile(params)
            console.log(`Solved the captcha ${res.id}`)
            console.log(res)
            await page.evaluate((token) => {
                cfCallback(token)
            }, res.data)
        } catch (e) {
            console.log(e.err)
            return process.exit()
        }
    } else {
        return;
    }
})

page.goto('https://rucaptcha.com/42')

That's it

This simple demo shows that the whole process is really easy and the integration with 2Captcha API is fast and seamless.

The full demo code can be found in the GitHub repository: https://github.com/2captcha/cloudflare-demo

References

Learn how to bypass Cloudflare Turnstile (not Cloudflare Challenge) on any website.