This example demonstrates how to bypass the Cloudflare Challenge page captcha located on https://2captcha.com/demo/cloudflare-turnstile-challenge using python. The pyppeteer tool is used for automation. The captcha is solved in the 2captcha service.
Cloudflare Challenge page - is a captcha that is displayed as a separate page, preventing the site from opening. Bypassing this captcha requires an unusual approach. The solution is to inject code into the page before it loads, this example uses page.evaluateOnNewDocument
provided by pyppeteer. Then the embedded code intercepts the parameters of the found turnstile captcha, the captcha is sent to 2captcha, after receiving the result the answer is applied on the page.
The idea and some of the code is based on this repository https://github.com/2captcha/cloudflare-demo. You can read more about bypassing this type of captcha in the article Bypassing Cloudflare Challenge with Puppeteer and 2Captcha.
This example can be used to bypass most Cloudflare Challenge page captchas. To use it, just replace the URL with yours. Also in some cases you may encounter additional protection methods, such as Cloudflare blocking, in such cases you should first find out how to bypass Cloudflare blocking and then solve the captcha.
-
Clone repo:
git clone https://github.com/bernard-dali/cloudflare-bypass-python-demo.git
-
Install dependencies:
pip install -r requirements.txt
-
Set apikey in
main.py
:apikey = "2captcha api key"
-
Run:
python main.py
Python source code:
import asyncio
import os
import json
PYPPETEER_CHROMIUM_REVISION = '1263111'
os.environ['PYPPETEER_CHROMIUM_REVISION'] = PYPPETEER_CHROMIUM_REVISION
from pyppeteer import launch
import time
import requests
apikey = "2captcha api key"
async def main():
browser = await launch(headless=False, devtools=True, autoClose=False, args=['--no-sandbox', '--disable-setuid-sandbox'])
page = await browser.newPage()
# Executing the javascript code on the page
await page.evaluateOnNewDocument(
"""
() => {
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
}
// we will intercept the message in puppeeter
console.log('intercepted-params:' + JSON.stringify(params))
window.cfCallback = b.callback
return
}
}
}, 50)
}
"""
)
# Intercept console messages to catch a message containing 'intercepted-params:'
async def console_message_handler(msg):
print(f"Dialog message: {msg}")
txt = msg.text
print(txt)
if 'intercepted-params:' in txt:
params = json.loads(txt.replace('intercepted-params:', ''))
print(params)
try:
# Captcha params
payload = {
"key": apikey,
"method": "turnstile",
"sitekey": params["sitekey"],
"pageurl": params["pageurl"],
"data": params["data"],
"pagedata": params["pagedata"],
"action": params["action"],
"useragent": params["userAgent"],
"json": 1,
}
# Send captcha to 2captcha
response = requests.post(f"https://2captcha.com/in.php?", data=payload)
print("Captcha sent")
print(response.text)
captcha_id = response.json()["request"]
time.sleep(2)
# Getting a captcha response
while True:
solution = requests.get(f"https://2captcha.com/res.php?key={apikey}&action=get&json=1&id={captcha_id}").json()
if solution["request"] == "CAPCHA_NOT_READY":
print(solution["request"])
time.sleep(1)
elif "ERROR" in solution["request"]:
print(solution["request"])
else:
print(solution)
break
# Use the received captcha response. Pass the answer to the configured callback function `cfCallback`
await page.evaluate('cfCallback', solution["request"])
except Exception as e:
print(e)
await browser.close()
else:
return
# Watch the console
page.on('console', lambda msg: asyncio.ensure_future(console_message_handler(msg)))
# Open target page
# Just change this url to the target page you want
await page.goto('https://2captcha.com/demo/cloudflare-turnstile-challenge')
# Create an asyncio event loop and run function main()
loop = asyncio.get_event_loop()
loop.run_until_complete(main())