Was this helpful?
How to bypass Tencent captcha using Playwright
Technical engineer
Tencent Captcha is a token-based protection system commonly found on sites built with Tencent Cloud infrastructure. The key challenge when automating this captcha is that simply passing the page URL is not enough. You must specify the exact URL of the captcha script (captchaScript), and after receiving the response, correctly inject two parameters: ticket and randstr.
In this guide, we will walk through how to automate Tencent Captcha in Playwright with Python: find the required parameters in the page code or network requests, send the task to the 2Captcha API, and properly inject the response tokens so the form accepts them as the result of a real user's actions.
What You Will Need
- Python 3.7 or higher
- Installed Playwright
- 2Captcha account and API key
- Target page URL with Tencent Captcha
- Optional: proxy, if the site is sensitive to datacenter IP addresses
Step 1. Installing Dependencies
Install the required libraries and Playwright browsers:
bash
pip install playwright 2captcha-python
playwright install chromium
Step 2. Browser Initialization and Parameter Discovery
Start by opening the page and waiting for the widget to appear. For debugging, use visible mode headless=False.
python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
page.goto("https://example.com/target-page-with-tencent")
# Wait for the Tencent Captcha widget or iframe to appear
page.wait_for_selector("#tcaptcha_iframe, #tcaptcha_popup, [data-tencent-captcha]")
Two critically important parameters are needed for solving: appid and captchaScript.
How to find appid
It is usually stored in the data-appid attribute of the widget container or passed in the JavaScript initialization code. You can also find it in the Network tab in requests to captcha.qq.com or ssl.captcha.qq.com as the aid or appId parameter.
How to find captchaScript (MANDATORY)
Attention: The captchaScript parameter is mandatory for correct Tencent Captcha solving via the API. Without specifying the exact script URL that the site uses, the environment emulation will be incorrect, and the captcha will not be solved.
The script URL can be found in the Network tab by filtering requests for the word TCaptcha. Most commonly, sites use one of the following popular variants:
- https://turing.captcha.qcloud.com/TCaptcha.js (Standard / Default)
- https://ca.turing.captcha.qcloud.com/TCaptcha-global.js (Global CDN)
- https://global.captcha.gtimg.com/TCaptcha-global.js (Tencent Global CDN)
- https://captchacdn.tencentcloudcs.com/TCaptcha-global.js (Tencent Cloud CDN)
If the site uses a custom domain, simply copy the full script URL from the Network tab.
Step 3. Sending the Task to the API and Getting Tokens
We will use the official Python SDK. It automatically creates a task and polls the server until a result is obtained.
python
from twocaptcha import TwoCaptcha
solver = TwoCaptcha('YOUR_API_KEY')
result = solver.tencent(
appid='2047454578', # Replace with the real appid
url='https://example.com/target-page-with-tencent',
captchaScript='https://turing.captcha.qcloud.com/TCaptcha.js' # You must specify the correct URL
)
print(f"Result: {result}")
# Result contains 'code' (this is the ticket) and 'randstr'
Note: If you prefer asynchronous code, check out the official example of using async options in the repository: async_tencent_options.py (https://github.com/2captcha/2captcha-python/blob/master/examples/async/async_tencent_options.py).
Alternative (direct HTTP request via curl):
bash
curl -X POST https://api.2captcha.com/createTask \
-H "Content-Type: application/json" \
-d '{
"clientKey": "YOUR_API_KEY",
"task": {
"type": "TencentCaptchaTaskProxyless",
"websiteURL": "https://example.com/target-page-with-tencent",
"appID": "2047454578",
"captchaScript": "https://turing.captcha.qcloud.com/TCaptcha.js"
}
}'
Step 4. Injecting Tokens into the Form
Tencent Captcha returns two values: ticket (the main token) and randstr (an additional string for validation). Both values must be injected into the page.
Usually, sites expect a JavaScript callback to be triggered, which passes this data back to the widget.
python
ticket = result['code']
randstr = result.get('randstr', '@') # If randstr is absent, '@' is sometimes used
page.evaluate(f"""
// 1. Inject tokens into hidden form fields (if the site uses classic form submission)
const form = document.querySelector('form');
let ticketField = form.querySelector('input[name="ticket"], input[name="tc_token"]');
if (!ticketField) {{
ticketField = document.createElement('input');
ticketField.type = 'hidden';
ticketField.name = 'ticket';
form.appendChild(ticketField);
}}
ticketField.value = "{ticket}";
let randstrField = form.querySelector('input[name="randstr"]');
if (!randstrField) {{
randstrField = document.createElement('input');
randstrField.type = 'hidden';
randstrField.name = 'randstr';
form.appendChild(randstrField);
}}
randstrField.value = "{randstr}";
// 2. Call the callback function (the name may differ, check the initialization code)
// Often this is window.TencentCaptchaCallback or a similar function
if (typeof window.TencentCaptchaCallback === 'function') {{
window.TencentCaptchaCallback({{
ticket: "{ticket}",
randstr: "{randstr}",
code: 0
}});
}}
""")
Step 5. Submitting the Form
After successfully injecting the tokens and triggering the callback, the form should unlock.
python
page.click("button[type='submit']")
page.wait_for_load_state("networkidle")
browser.close()
Full Working Example (Python)
python
from playwright.sync_api import sync_playwright
from twocaptcha import TwoCaptcha
API_KEY = "YOUR_API_KEY"
TARGET_URL = "https://example.com/target-page-with-tencent"
APP_ID = "2047454578" # Replace with the real one
CAPTCHA_SCRIPT = "https://turing.captcha.qcloud.com/TCaptcha.js" # Replace with the real script URL
def solve_tencent_captcha():
solver = TwoCaptcha(API_KEY)
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
try:
page.goto(TARGET_URL)
page.wait_for_selector("#tcaptcha_iframe, #tcaptcha_popup, [data-appid]", timeout=10000)
print("Sending task to API...")
# Solve captcha with mandatory captchaScript parameter
result = solver.tencent(
appid=APP_ID,
url=TARGET_URL,
captchaScript=CAPTCHA_SCRIPT
)
ticket = result['code']
randstr = result.get('randstr', '@')
print(f"Token received! Ticket: {ticket[:20]}..., Randstr: {randstr}")
# Inject tokens and trigger callback
page.evaluate(f"""
const form = document.querySelector('form') || document.body;
let ticketField = form.querySelector('input[name="ticket"], input[name="tc_token"]');
if (!ticketField) {{
ticketField = document.createElement('input');
ticketField.type = 'hidden';
ticketField.name = 'ticket';
form.appendChild(ticketField);
}}
ticketField.value = "{ticket}";
let randstrField = form.querySelector('input[name="randstr"]');
if (!randstrField) {{
randstrField = document.createElement('input');
randstrField.type = 'hidden';
randstrField.name = 'randstr';
form.appendChild(randstrField);
}}
randstrField.value = "{randstr}";
if (typeof window.TencentCaptchaCallback === 'function') {{
window.TencentCaptchaCallback({{
ticket: "{ticket}",
randstr: "{randstr}",
code: 0
}});
}}
""")
# Attempt to submit the form
submit_btn = page.locator("button[type='submit'], input[type='submit']").first
if submit_btn.is_visible():
submit_btn.click()
page.wait_for_load_state("networkidle")
print("Form submitted successfully!")
else:
print("Submit button not found or form already processed by callback.")
page.wait_for_timeout(3000) # Pause for visual verification
except Exception as e:
print(f"Error: {e}")
finally:
browser.close()
if __name__ == "__main__":
solve_tencent_captcha()
Troubleshooting Common Issues
| Issue | Cause and Solution |
|---|---|
| Captcha is not solved or returns a behavior error | You did not specify the captchaScript parameter or provided an incorrect URL. This is the most common mistake. Check the Network tab and make sure the script URL matches what the site loads. |
| AppID not found (returns None) | The widget loads inside a dynamic iframe. Go to the Network tab, filter by aid or appId, and extract the value from the URL of the request to Tencent servers. |
| Form does not submit after token injection | The site expects a specific callback function to be triggered. Check the page source code (search for new TencentCaptcha or TencentCaptchaCallback) and call the required function via page.evaluate, passing an object with ticket and randstr. |
| Script works in visible mode but fails in headless | This is headless mode detection by the anti-bot system. Use masking libraries (e.g., playwright-stealth) or pass high-quality residential proxies to the API. |
Conclusion
Automating Tencent Captcha in Playwright requires attention to detail. Unlike some other captchas, it is critically important here not only to find the appid but also to pass the correct captchaScript URL. Without this, the environment emulation will be incomplete, and the protection will block the solution.
After receiving the ticket and randstr pair from the API, you need to correctly inject them both as hidden form fields and through the JavaScript callback that the specific site expects. By following this guide and carefully checking the network requests of the target page, you will be able to reliably bypass Tencent Captcha in your automation projects.
Useful Links
- 2Captcha API documentation for Tencent Captcha: https://2captcha.com/api-docs/tencent-captcha
- Async Python example (GitHub): https://github.com/2captcha/2captcha-python/blob/master/examples/async/async_tencent_options.py
- 2Captcha Python SDK on GitHub: https://github.com/2captcha/2captcha-python