How to bypass Cloudflare Turnstile captcha
Cloudflare Turnstile protects website forms and pages from automated submissions. It may run invisibly, display a checkbox, or request additional verification when Cloudflare considers a browser session suspicious.
For authorized browser automation, application testing, and data collection, Turnstile can be processed through the SolveCaptcha Cloudflare captcha solver.
This guide explains how to:
- distinguish standalone Turnstile from a Cloudflare Challenge Page;
- find the Turnstile site key;
- submit a task to the SolveCaptcha API;
- poll the API for the result;
- apply the returned token to the protected form;
- automate the complete process with Python;
- handle callbacks, proxies, expired challenges, and API errors.
This article focuses primarily on standalone Cloudflare Turnstile, where the widget is embedded directly into a website form. Cloudflare Challenge Pages require additional parameters and a separate browser-based integration.
Use these methods only on websites you own or are authorized to test and automate.
What is Cloudflare Turnstile?
Cloudflare Turnstile is a verification system that helps websites distinguish legitimate visitors from automated traffic.
A website can embed Turnstile into:
- login forms;
- registration forms;
- checkout pages;
- contact forms;
- password reset pages;
- comment forms;
- account recovery flows;
- API access forms.
A basic Turnstile widget may look like this:
<div
class="cf-turnstile"
data-sitekey="0x4AAAAAAExampleSiteKey"
></div>
After successful verification, Turnstile generates a response token. The website sends this token to its backend, where it is validated through Cloudflare.
Common fields used to store the token are:
cf-turnstile-response
and, when reCAPTCHA compatibility mode is enabled:
g-recaptcha-response
A website may also process the token through a JavaScript callback.
Standalone Turnstile and Cloudflare Challenge Page
Turnstile is commonly used in two different scenarios.
Standalone Turnstile
The widget is embedded directly into a normal website page.
Typical signs:
- the website content is already visible;
- the captcha appears inside a form;
- the page contains a
data-sitekeyattribute; - there is no full-screen Cloudflare verification page;
- only the site key and complete page URL are normally required.
For this type, submit:
sitekey
pageurl
Cloudflare Challenge Page
Cloudflare may display an intermediate verification page before allowing access to the website.
Typical signs:
- the website content is hidden;
- the page displays “Verifying you are human” or “Just a moment...”;
- a Cloudflare Ray ID may be visible;
- the page dynamically calls
turnstile.render(); - additional challenge parameters are generated.
A Challenge Page requires:
sitekey
pageurl
action
data
pagedata
The parameter mapping is:
Cloudflare value SolveCaptcha parameter
-------------------------------------------
sitekey sitekey
cData data
chlPageData pagedata
action action
The standalone method described below should not be used for a Challenge Page without these additional values.
How Turnstile solving works
The integration consists of four stages:
- Find the Turnstile site key and page URL.
- Submit them to SolveCaptcha.
- Poll the API until the token is ready.
- Add the token to the form or pass it to the callback.
SolveCaptcha uses the following endpoints:
Create a task:
POST https://api.solvecaptcha.com/in.php
Get the result:
GET https://api.solvecaptcha.com/res.php
The solving method is:
turnstile
Requirements
Before starting, prepare:
- a SolveCaptcha account;
- your API key;
- Python 3.10 or newer;
- the
requestspackage; - the page URL;
- the Turnstile site key.
Install Requests:
python -m pip install requests
Set your API key as an environment variable.
Linux or macOS:
export SOLVECAPTCHA_API_KEY="YOUR_API_KEY"
Windows PowerShell:
$env:SOLVECAPTCHA_API_KEY="YOUR_API_KEY"
Do not publish an API key in source code or a public repository.
How to find the Turnstile site key
The site key is a public identifier used by the browser to initialize the widget.
There are several ways to find it.
Find data-sitekey in HTML
Open the protected page and launch developer tools:
- Windows or Linux:
Ctrl+Shift+I; - macOS:
Cmd+Option+I.
Open the Elements tab and search for:
data-sitekey
Example:
<div
class="cf-turnstile"
data-sitekey="0x4AAAAAAExampleSiteKey"
></div>
The site key is:
0x4AAAAAAExampleSiteKey
Search for cf-turnstile
You can also search the page for:
cf-turnstile
Example:
<div
class="cf-turnstile"
data-sitekey="0x4AAAAAAExampleSiteKey"
data-action="login"
></div>
Find the key in turnstile.render
Some websites render the widget through JavaScript:
turnstile.render("#turnstile-container", {
sitekey: "0x4AAAAAAExampleSiteKey",
callback: function (token) {
submitForm(token);
}
});
Search the loaded JavaScript files for:
turnstile.render
sitekey
Use the browser console
The following command returns all data-sitekey values found in the current document:
[
...new Set(
[...document.querySelectorAll("[data-sitekey]")]
.map((element) => element.getAttribute("data-sitekey"))
.filter(Boolean)
)
];
Example result:
[
"0x4AAAAAAExampleSiteKey"
]
How to identify the page URL
Use the complete URL where Turnstile is displayed.
Correct:
https://example.com/account/register?source=campaign
Incorrect:
https://example.com/
when the captcha is actually displayed on another page.
The page URL must preserve:
- protocol;
- hostname;
- path;
- query parameters.
In the SolveCaptcha request, it is submitted as:
pageurl
Submit Turnstile to SolveCaptcha
The minimum request for standalone Turnstile contains:
key
method
sitekey
pageurl
json
Example request parameters:
key=YOUR_API_KEY
method=turnstile
sitekey=0x4AAAAAAExampleSiteKey
pageurl=https://example.com/register
json=1
cURL example
curl --request POST \
--url https://api.solvecaptcha.com/in.php \
--data-urlencode "key=YOUR_API_KEY" \
--data-urlencode "method=turnstile" \
--data-urlencode "sitekey=0x4AAAAAAExampleSiteKey" \
--data-urlencode "pageurl=https://example.com/register" \
--data-urlencode "json=1"
A successful response contains the task ID:
{
"status": 1,
"request": "74327409378"
}
Save the value of request. It is required to retrieve the solution.
Get the Turnstile token
Send a request to:
https://api.solvecaptcha.com/res.php
Required parameters:
key=YOUR_API_KEY
action=get
id=74327409378
json=1
Example:
curl "https://api.solvecaptcha.com/res.php?key=YOUR_API_KEY&action=get&id=74327409378&json=1"
If the task is still processing, the API returns:
{
"status": 0,
"request": "CAPCHA_NOT_READY"
}
Wait five seconds and repeat the request using the same task ID.
Do not create another task while the original task is still processing.
A successful response contains the Turnstile token:
{
"status": 1,
"request": "0.4uMMZZdSfsVM8...610cd090"
}
The value of request is the token that must be applied to the target page.
For some Cloudflare Challenge Page tasks, the response may also contain:
{
"useragent": "Mozilla/5.0 ..."
}
Complete Python Turnstile solver
Create turnstile_solver.py:
#!/usr/bin/env python3
from __future__ import annotations
import os
import time
from dataclasses import dataclass
from typing import Any
import requests
CREATE_TASK_URL = "https://api.solvecaptcha.com/in.php"
GET_RESULT_URL = "https://api.solvecaptcha.com/res.php"
POLL_INTERVAL_SECONDS = 5
DEFAULT_TIMEOUT_SECONDS = 180
class SolveCaptchaError(RuntimeError):
"""Raised when SolveCaptcha returns an API error."""
@dataclass(frozen=True)
class TurnstileSolution:
task_id: str
token: str
user_agent: str | None = None
def parse_api_response(
response: requests.Response,
) -> dict[str, Any]:
response.raise_for_status()
try:
payload = response.json()
except requests.JSONDecodeError as exc:
raise SolveCaptchaError(
"SolveCaptcha returned invalid JSON: "
f"{response.text[:500]}"
) from exc
if not isinstance(payload, dict):
raise SolveCaptchaError(
f"Unexpected API response: {payload!r}"
)
return payload
class SolveCaptchaTurnstileClient:
def __init__(
self,
api_key: str,
request_timeout: float = 30,
) -> None:
if not api_key:
raise ValueError(
"SolveCaptcha API key is required"
)
self.api_key = api_key
self.request_timeout = request_timeout
self.session = requests.Session()
def create_task(
self,
*,
sitekey: str,
pageurl: str,
action: str | None = None,
data: str | None = None,
pagedata: str | None = None,
proxy: str | None = None,
proxytype: str | None = None,
) -> str:
if not sitekey:
raise ValueError(
"Turnstile site key is required"
)
if not pageurl:
raise ValueError(
"Page URL is required"
)
payload: dict[str, Any] = {
"key": self.api_key,
"method": "turnstile",
"sitekey": sitekey,
"pageurl": pageurl,
"json": 1,
}
if action:
payload["action"] = action
if data:
payload["data"] = data
if pagedata:
payload["pagedata"] = pagedata
if proxy:
payload["proxy"] = proxy
if proxytype:
payload["proxytype"] = proxytype
response = self.session.post(
CREATE_TASK_URL,
data=payload,
timeout=self.request_timeout,
)
result = parse_api_response(response)
if result.get("status") != 1:
error_code = str(
result.get(
"request",
"UNKNOWN_ERROR",
)
)
raise SolveCaptchaError(
"Unable to create Turnstile task: "
f"{error_code}"
)
task_id = str(
result.get("request", "")
).strip()
if not task_id:
raise SolveCaptchaError(
"SolveCaptcha did not return "
"a task ID"
)
return task_id
def get_result(
self,
task_id: str,
) -> TurnstileSolution | None:
response = self.session.get(
GET_RESULT_URL,
params={
"key": self.api_key,
"action": "get",
"id": task_id,
"json": 1,
},
timeout=self.request_timeout,
)
result = parse_api_response(response)
if result.get("status") == 1:
token = str(
result.get("request", "")
).strip()
if not token:
raise SolveCaptchaError(
"SolveCaptcha returned "
"an empty token"
)
returned_user_agent = result.get(
"useragent"
)
return TurnstileSolution(
task_id=task_id,
token=token,
user_agent=(
str(returned_user_agent)
if returned_user_agent
else None
),
)
error_code = str(
result.get(
"request",
"UNKNOWN_ERROR",
)
)
if error_code == "CAPCHA_NOT_READY":
return None
raise SolveCaptchaError(
f"Turnstile task {task_id} failed: "
f"{error_code}"
)
def solve(
self,
*,
sitekey: str,
pageurl: str,
action: str | None = None,
data: str | None = None,
pagedata: str | None = None,
proxy: str | None = None,
proxytype: str | None = None,
max_wait: float = DEFAULT_TIMEOUT_SECONDS,
) -> TurnstileSolution:
task_id = self.create_task(
sitekey=sitekey,
pageurl=pageurl,
action=action,
data=data,
pagedata=pagedata,
proxy=proxy,
proxytype=proxytype,
)
deadline = time.monotonic() + max_wait
while time.monotonic() < deadline:
time.sleep(
POLL_INTERVAL_SECONDS
)
result = self.get_result(
task_id
)
if result is not None:
return result
raise TimeoutError(
f"Turnstile task {task_id} was not "
f"completed within {max_wait:.0f} seconds"
)
def main() -> None:
api_key = os.environ.get(
"SOLVECAPTCHA_API_KEY",
"",
).strip()
sitekey = os.environ.get(
"TURNSTILE_SITEKEY",
"",
).strip()
pageurl = os.environ.get(
"TURNSTILE_PAGEURL",
"",
).strip()
if not api_key:
raise SystemExit(
"Set SOLVECAPTCHA_API_KEY"
)
if not sitekey:
raise SystemExit(
"Set TURNSTILE_SITEKEY"
)
if not pageurl:
raise SystemExit(
"Set TURNSTILE_PAGEURL"
)
client = SolveCaptchaTurnstileClient(
api_key=api_key
)
solution = client.solve(
sitekey=sitekey,
pageurl=pageurl,
)
print("Task ID:", solution.task_id)
print("Token:", solution.token)
if solution.user_agent:
print(
"User-Agent:",
solution.user_agent,
)
if __name__ == "__main__":
main()
Set the required variables:
export SOLVECAPTCHA_API_KEY="YOUR_API_KEY"
export TURNSTILE_SITEKEY="0x4AAAAAAExampleSiteKey"
export TURNSTILE_PAGEURL="https://example.com/register"
Run the script:
python turnstile_solver.py
Example result:
Task ID: 74327409378
Token: 0.4uMMZZdSfsVM8...610cd090
Minimal Python example
For a shorter integration:
import os
import time
import requests
API_KEY = os.environ[
"SOLVECAPTCHA_API_KEY"
]
SITEKEY = "0x4AAAAAAExampleSiteKey"
PAGE_URL = "https://example.com/register"
created = requests.post(
"https://api.solvecaptcha.com/in.php",
data={
"key": API_KEY,
"method": "turnstile",
"sitekey": SITEKEY,
"pageurl": PAGE_URL,
"json": 1,
},
timeout=30,
).json()
if created.get("status") != 1:
raise RuntimeError(
"Task creation failed: "
f"{created.get('request')}"
)
task_id = created["request"]
while True:
time.sleep(5)
result = requests.get(
"https://api.solvecaptcha.com/res.php",
params={
"key": API_KEY,
"action": "get",
"id": task_id,
"json": 1,
},
timeout=30,
).json()
if result.get("status") == 1:
token = result["request"]
break
if result.get("request") != "CAPCHA_NOT_READY":
raise RuntimeError(
"Task failed: "
f"{result.get('request')}"
)
print(token)
How to apply the Turnstile token
The token is normally placed in an input named:
cf-turnstile-response
Example:
<input
type="hidden"
name="cf-turnstile-response"
>
Set the value with JavaScript:
const token = "TOKEN_FROM_SOLVECAPTCHA";
const field = document.querySelector(
'[name="cf-turnstile-response"]'
);
if (field) {
field.value = token;
field.dispatchEvent(
new Event("input", {
bubbles: true
})
);
field.dispatchEvent(
new Event("change", {
bubbles: true
})
);
}
When compatibility mode is enabled, update both common response fields:
const token = "TOKEN_FROM_SOLVECAPTCHA";
const selectors = [
'[name="cf-turnstile-response"]',
'[name="g-recaptcha-response"]'
];
for (const selector of selectors) {
document
.querySelectorAll(selector)
.forEach((field) => {
field.value = token;
field.innerHTML = token;
field.dispatchEvent(
new Event("input", {
bubbles: true
})
);
field.dispatchEvent(
new Event("change", {
bubbles: true
})
);
});
}
After setting the value, submit the relevant form:
document
.querySelector("#registration-form")
.requestSubmit();
Use the actual form selector from the target page.
Apply the token with Selenium
Install Selenium:
python -m pip install selenium
Example:
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
try:
driver.get(
"https://example.com/register"
)
token = solution.token
result = driver.execute_script(
"""
const token = arguments[0];
const selectors = [
'[name="cf-turnstile-response"]',
'[name="g-recaptcha-response"]'
];
let updated = 0;
for (const selector of selectors) {
document
.querySelectorAll(selector)
.forEach((field) => {
field.value = token;
field.innerHTML = token;
field.dispatchEvent(
new Event("input", {
bubbles: true
})
);
field.dispatchEvent(
new Event("change", {
bubbles: true
})
);
updated += 1;
});
}
return updated;
""",
token,
)
if result == 0:
raise RuntimeError(
"Turnstile response field "
"was not found"
)
form = driver.find_element(
By.CSS_SELECTOR,
"#registration-form",
)
form.submit()
finally:
driver.quit()
The page must remain in the same session while the captcha is being solved.
Do not:
- refresh the page;
- change the proxy;
- navigate to another page;
- recreate the Turnstile widget;
- reuse the token in another session.
Using a callback
A website may define a callback through the data-callback attribute:
<div
class="cf-turnstile"
data-sitekey="0x4AAAAAAExampleSiteKey"
data-callback="onTurnstileSuccess"
></div>
After receiving the token, call:
onTurnstileSuccess(
"TOKEN_FROM_SOLVECAPTCHA"
);
The callback may also be defined through turnstile.render():
turnstile.render(
"#turnstile-container",
{
sitekey: "0x4AAAAAAExampleSiteKey",
callback: function (token) {
submitProtectedForm(token);
}
}
);
When a callback is used, simply changing the hidden input may not continue the website workflow. Call the callback with the returned token.
Do not call an arbitrary function. Identify the real callback from:
- the
data-callbackattribute; - the
turnstile.render()configuration; - the website’s JavaScript source;
- browser DevTools breakpoints.
Using a proxy
The SolveCaptcha Turnstile request supports optional proxy parameters:
proxy
proxytype
Example:
solution = client.solve(
sitekey="0x4AAAAAAExampleSiteKey",
pageurl="https://example.com/register",
proxy=(
"login:password@"
"proxy.example.com:8000"
),
proxytype="http",
)
Supported proxy types are:
HTTP
HTTPS
SOCKS4
SOCKS5
When the target browser uses a proxy, keep the same proxy throughout the workflow:
Open page
→ extract site key
→ create task
→ receive token
→ apply token
→ submit form
Changing the IP address can invalidate the active session or cause the website to display another challenge.
Cloudflare Challenge Page parameters
A Cloudflare Challenge Page requires additional values:
action
data
pagedata
These correspond to values passed to turnstile.render():
window.turnstile.render = (
container,
options
) => {
const parameters = {
sitekey: options.sitekey,
pageurl: window.location.href,
data: options.cData,
pagedata: options.chlPageData,
action: options.action
};
window.turnstileCallback =
options.callback;
console.log(parameters);
return "solvecaptcha-widget";
};
The resulting API request contains:
solution = client.solve(
sitekey=parameters["sitekey"],
pageurl=parameters["pageurl"],
action=parameters["action"],
data=parameters["data"],
pagedata=parameters["pagedata"],
)
After receiving the token:
window.turnstileCallback(
"TOKEN_FROM_SOLVECAPTCHA"
);
The interception code must be installed before the widget initializes. Injecting it after the Challenge Page has already called turnstile.render() may be too late.
For a complete browser implementation, use the dedicated guide for bypassing Cloudflare Challenge with Python and Selenium.
Handle CAPCHA_NOT_READY
This response means the task is still being processed:
{
"status": 0,
"request": "CAPCHA_NOT_READY"
}
Correct behavior:
- Keep the same task ID.
- Wait five seconds.
- Request the result again.
- Stop after a defined timeout.
Do not submit duplicate tasks for the same challenge.
Handle ERROR_CAPTCHA_UNSOLVABLE
This error means the challenge could not be solved reliably.
Possible causes include:
- an incorrect site key;
- an incorrect page URL;
- expired Challenge Page parameters;
- missing
data; - missing
pagedata; - missing
action; - proxy failure;
- a changed browser session;
- unsupported challenge state.
Recommended action:
- Check all request parameters.
- Confirm whether the captcha is standalone or a Challenge Page.
- Reload the challenge when necessary.
- Extract fresh values.
- Create a new task.
- Limit the number of retries.
Do not repeatedly submit the same expired Challenge Page parameters.
Handle ERROR_WRONG_USER_KEY
The API key is invalid.
Verify:
SOLVECAPTCHA_API_KEY
Stop creating tasks until the key is corrected.
Handle ERROR_ZERO_BALANCE
The SolveCaptcha account does not have enough balance.
Stop task creation until the balance is replenished.
Handle proxy errors
Proxy errors may be caused by:
- invalid credentials;
- incorrect proxy type;
- proxy timeout;
- blocked proxy IP;
- unsupported authentication;
- connection restrictions.
Test the proxy separately before submitting another captcha task.
Turnstile tokens are session-specific
Apply the token as soon as it is returned.
Do not:
- store tokens for future sessions;
- reuse one token for multiple forms;
- apply a token to another domain;
- use a token after the widget resets;
- use a token after reloading the page;
- submit the same token more than once.
If the page generates another challenge, create a new SolveCaptcha task.
How to determine whether the token was accepted
Possible success indicators include:
- the form is submitted;
- the page redirects;
- a success message appears;
- the Turnstile widget disappears;
- a protected button becomes enabled;
- the server returns a successful response;
- a callback changes the page state.
Example Selenium check:
from selenium.webdriver.support import (
expected_conditions as EC,
)
from selenium.webdriver.support.ui import (
WebDriverWait,
)
WebDriverWait(
driver,
15,
).until(
EC.url_changes(
"https://example.com/register"
)
)
For forms submitted through XHR, inspect the actual response rather than waiting for navigation.
Reporting correct and incorrect answers
After determining whether the token was accepted, you can report the result.
Correct solution:
https://api.solvecaptcha.com/res.php?key=YOUR_API_KEY&action=reportgood&id=TASK_ID
Incorrect solution:
https://api.solvecaptcha.com/res.php?key=YOUR_API_KEY&action=reportbad&id=TASK_ID
Use reportbad only when the token itself was rejected.
Do not report a solution as incorrect when the failure was caused by:
- an expired page;
- an incorrect form selector;
- a missing callback call;
- a changed proxy;
- a browser restart;
- missing Challenge Page parameters;
- application-level validation unrelated to Turnstile.
Common mistakes
Using the wrong API method
Use:
method=turnstile
Sending websiteKey instead of sitekey
The SolveCaptcha API documented in this guide expects:
sitekey
Sending websiteURL instead of pageurl
Use:
pageurl
Using createTask and getTaskResult
The documented SolveCaptcha integration in this guide uses:
https://api.solvecaptcha.com/in.php
and:
https://api.solvecaptcha.com/res.php
Treating a Challenge Page as standalone Turnstile
Challenge Pages require:
action
data
pagedata
Applying the token to the wrong input
The common field is:
cf-turnstile-response
Compatibility mode may also use:
g-recaptcha-response
Ignoring the callback
Some pages continue only after the configured callback receives the token.
Reusing an expired token
Create a new task for every new challenge.
Refreshing the page while waiting
A refresh can replace the current widget and invalidate the pending solution.
How to reduce Turnstile challenges
Avoiding unnecessary captcha triggers is usually more efficient than solving every challenge.
Recommended practices:
- limit request frequency;
- avoid sudden traffic spikes;
- preserve cookies between related requests;
- keep a stable browser session;
- use consistent headers;
- avoid changing User-Agent mid-session;
- avoid rotating IP addresses during one workflow;
- follow the website’s rate limits;
- use documented APIs when available.
A proxy does not automatically prevent Turnstile. Low-quality or heavily reused proxy addresses may increase challenge frequency.
Testing Turnstile on your own website
For automated testing of an application you control, use Cloudflare testing configurations or mock the verification response in development and staging environments.
A practical test strategy is:
- Use a predictable test configuration for routine CI tests.
- Test frontend behavior with mocked successful and failed tokens.
- Test backend Siteverify handling separately.
- Run a limited end-to-end test against the real integration.
- Keep production captcha solving outside ordinary unit tests.
This makes tests faster and more stable.
Frequently asked questions
Which method is used for Cloudflare Turnstile?
Use:
method=turnstile
Which endpoints should I use?
Create a task:
https://api.solvecaptcha.com/in.php
Get the result:
https://api.solvecaptcha.com/res.php
Which parameters are required for standalone Turnstile?
Use:
key
method
sitekey
pageurl
Set:
json=1
to receive JSON responses.
Which parameters are required for a Challenge Page?
In addition to the site key and page URL, provide:
action
data
pagedata
Where can I find the site key?
Look for:
data-sitekey
or the sitekey value passed to:
turnstile.render()
How often should I request the result?
Wait five seconds between requests while the API returns:
CAPCHA_NOT_READY
Where is the token returned?
In a successful JSON response, the token is stored in:
request
Where should the token be inserted?
The most common field is:
cf-turnstile-response
The page may also use:
g-recaptcha-response
or a callback function.
Is a proxy required?
No. The SolveCaptcha documentation lists proxy parameters as optional for Turnstile. Use them when the target workflow requires a consistent proxy session.
Can the same token be reused?
No. Treat each token as challenge-specific and single-use.
Why does the token fail?
Common causes include:
- incorrect site key;
- incorrect page URL;
- expired token;
- refreshed widget;
- missing callback execution;
- incorrect input field;
- changed proxy;
- using the standalone method for a Challenge Page.
Conclusion
Bypassing a standalone Cloudflare Turnstile captcha with SolveCaptcha requires four main steps:
- Find the Turnstile site key.
- Submit the site key and page URL to
in.php. - Poll
res.phpuntil the token is ready. - Insert the token into the response field or pass it to the configured callback.
For a standard embedded widget, the main parameters are:
method=turnstile
sitekey=SITE_KEY
pageurl=FULL_PAGE_URL
Cloudflare Challenge Pages require additional parameters:
action
data
pagedata
Keep the page session stable, apply the token immediately, and create a new task whenever the challenge changes.
Use the SolveCaptcha Turnstile API documentation for the complete parameter list and the Cloudflare captcha solver for service details.
How to bypass Cloudflare Turnstile with a browser extension
Learn how to solve Cloudflare Turnstile and Challenge Pages with the SolveCaptcha browser extension, enable auto-solve, and troubleshoot failed solutions.
How to bypass Cloudflare Turnstile with a browser extension
Cloudflare Turnstile protects forms and websites from automated activity. Depending on the configuration, it may display a checkbox, run without visible interaction, or appear as part of a full Cloudflare verification page.
For manual testing and browser-based workflows, writing a separate automation script for every protected page is often unnecessary. The SolveCaptcha browser extension detects supported captcha widgets, sends their parameters to SolveCaptcha, receives a solution, and applies it directly to the current page.
This guide explains how to:
- install the SolveCaptcha extension;
- connect it to your account;
- solve standalone Turnstile widgets;
- work with Cloudflare Challenge Pages;
- enable automatic solving;
- troubleshoot undetected widgets and rejected tokens;
- report accepted or incorrect solutions.
Use the extension only on websites you own or are authorized to test and automate.
What is Cloudflare Turnstile?
Cloudflare Turnstile is a verification system designed to protect forms and pages from automated submissions and malicious traffic.
Unlike traditional image captchas, Turnstile can complete verification without asking the visitor to select objects or type text. Depending on the website configuration and assessed risk, the widget may operate in several ways:
- without visible interaction;
- as a non-interactive verification widget;
- as a managed widget that requests interaction when necessary.
Cloudflare may also evaluate the wider request context, including:
- browser environment;
- IP reputation;
- cookies and session state;
- page URL;
- widget configuration;
- interaction history.
A valid Turnstile solution is returned as a token. The website normally sends this token to its backend for verification.
Standalone Turnstile and Cloudflare Challenge Page
Turnstile commonly appears in two different scenarios.
Standalone Turnstile widget
A standalone widget is embedded directly into a normal website page.
It may appear inside:
- a login form;
- a registration form;
- a checkout page;
- a contact form;
- a password recovery flow.
A basic implementation may look like this:
<div
class="cf-turnstile"
data-sitekey="0x4AAAAAAExampleSiteKey"
></div>