How to bypass reCAPTCHA v3
reCAPTCHA v3 is a score-based verification system that runs in the background without requiring the user to select images or click an “I’m not a robot” checkbox.
Instead of displaying a visible challenge, reCAPTCHA v3 generates a token associated with:
- the website’s public site key;
- the current page URL;
- the action performed by the user;
- a score representing the assessed legitimacy of the interaction.
For authorized browser automation, application testing, and data collection, the token can be obtained through the SolveCaptcha reCAPTCHA solver.
This guide explains how to:
- identify reCAPTCHA v3 on a page;
- find the site key and action;
- configure
min_score; - submit the task to SolveCaptcha;
- retrieve the response token;
- apply the token to the target request;
- report accepted and rejected solutions;
- integrate the process with Python and PHP.
Use this method only on websites you own or are authorized to test and automate.
What is reCAPTCHA v3?
reCAPTCHA v3 evaluates browser activity without interrupting the user with a visible puzzle.
The website loads the reCAPTCHA JavaScript API and executes an action:
grecaptcha.execute(
"SITE_KEY",
{
action: "login"
}
);
Google returns a token to the website. The website sends that token to its backend, which verifies it and receives information that includes:
- whether the token is valid;
- the calculated score;
- the action associated with the token;
- other verification metadata.
The score normally ranges from:
0.1 to 0.9
A higher score indicates that the interaction appears more legitimate. The website decides which score is sufficient for a specific action.
For example, a website may accept:
0.3
for viewing public content but require a higher score for:
login
registration
checkout
password reset
reCAPTCHA v2 and v3 differences
| Feature | reCAPTCHA v2 | reCAPTCHA v3 |
|---|---|---|
| Visible checkbox | Common | No |
| Image challenge | Possible | No |
| Runs in background | Sometimes | Yes |
| Returns a score | No | Yes |
| Uses an action | Usually no | Common |
Requires version=v3 |
No | Yes |
Invisible reCAPTCHA v2 should not be confused with reCAPTCHA v3.
Invisible v2 may still display an image challenge when Google considers the interaction suspicious. reCAPTCHA v3 does not display an image-selection challenge and instead returns a score.
How to identify reCAPTCHA v3
The most reliable method is to inspect the page source and JavaScript.
Look for api.js with a render parameter
A reCAPTCHA v3 page commonly loads:
<script
src="https://www.google.com/recaptcha/api.js?render=SITE_KEY"
></script>
Example:
<script
src="https://www.google.com/recaptcha/api.js?render=6LfB5_IbAAAAAMCtsjEHEHKqcB9iQocwwxTiihJu"
></script>
The value of render is the site key:
6LfB5_IbAAAAAMCtsjEHEHKqcB9iQocwwxTiihJu
The script may also be loaded from:
https://www.recaptcha.net/recaptcha/api.js
Look for grecaptcha.execute
Search the page source and loaded JavaScript files for:
grecaptcha.execute
Example:
grecaptcha.execute(
"6LfB5_IbAAAAAMCtsjEHEHKqcB9iQocwwxTiihJu",
{
action: "login"
}
);
This call contains two important values:
Site key: 6LfB5_IbAAAAAMCtsjEHEHKqcB9iQocwwxTiihJu
Action: login
Check the reCAPTCHA configuration
Another possible indicator is:
___grecaptcha_cfg.clients[100000]
The configuration structure is not a stable public API, so it should be treated as a supporting indicator rather than the primary extraction method.
Use the browser console
The following command searches reCAPTCHA script URLs:
[
...document.querySelectorAll(
'script[src*="recaptcha/api.js"]'
)
].map((script) => {
try {
const url = new URL(script.src);
return {
src: script.src,
sitekey:
url.searchParams.get("render")
};
} catch {
return null;
}
});
A valid reCAPTCHA v3 site key appears in:
render=SITE_KEY
Do not treat:
render=explicit
as a site key.
Required SolveCaptcha parameters
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 required parameters are:
| Parameter | Required | Description |
|---|---|---|
key |
Yes | SolveCaptcha API key |
method |
Yes | Must be userrecaptcha |
version |
Yes | Must be v3 |
googlekey |
Yes | Public reCAPTCHA site key |
pageurl |
Yes | Full URL where reCAPTCHA is executed |
action |
No | Action used in grecaptcha.execute() |
min_score |
No | Requested score; default is 0.4 |
domain |
No | google.com or recaptcha.net |
json |
No | Set to 1 for JSON responses |
The parameter names are important.
Use:
googlekey
pageurl
action
min_score
Do not use API names from unrelated integrations such as:
websiteKey
websiteURL
pageAction
minScore
How to find the site key
The site key can be found in several locations.
api.js render parameter
<script
src="https://www.google.com/recaptcha/api.js?render=SITE_KEY"
></script>
grecaptcha.execute call
grecaptcha.execute(
"SITE_KEY",
{
action: "login"
}
);
iframe k parameter
In some implementations, the key may appear in a reCAPTCHA iframe URL:
https://www.google.com/recaptcha/api2/anchor?k=SITE_KEY
JavaScript configuration
The website may store the key in an application configuration object:
window.applicationConfig = {
recaptchaSiteKey:
"6LfB5_IbAAAAAMCtsjEHEHKqcB9iQocwwxTiihJu"
};
Search loaded JavaScript files for:
recaptchaSiteKey
sitekey
grecaptcha.execute
api.js?render=
How to find the action
The action is usually passed to:
grecaptcha.execute()
Example:
grecaptcha.execute(
"SITE_KEY",
{
action: "checkout"
}
);
The correct SolveCaptcha parameter is:
action=checkout
The value must match the action expected by the website.
Possible actions include:
login
register
signup
checkout
submit
contact
password_reset
verify
Do not choose an action based only on the form type. Inspect the website’s actual JavaScript or network requests.
If the page does not provide an action, SolveCaptcha uses:
verify
as the default value.
How to configure min_score
The min_score parameter specifies the score requested from SolveCaptcha.
Example:
min_score=0.3
The SolveCaptcha documentation defines a default value of:
0.4
However, the documentation also warns that obtaining tokens with scores above 0.3 can be difficult.
For this reason, do not automatically request:
0.9
unless the target website genuinely requires it and the integration has been tested with that threshold.
A practical starting configuration is:
min_score=0.3
The requested score does not guarantee that the website will accept the token. The target website can also check:
- whether the action matches;
- whether the token belongs to the correct site key;
- whether the token was generated for the correct page;
- whether the token is fresh;
- application-specific risk signals;
- session and request consistency.
Do not repeatedly create tasks with arbitrary score values. First determine the score threshold and action used by the target application.
Step 1: Create the task
Example request:
curl --request POST \
--url https://api.solvecaptcha.com/in.php \
--data-urlencode "key=YOUR_API_KEY" \
--data-urlencode "method=userrecaptcha" \
--data-urlencode "version=v3" \
--data-urlencode "googlekey=6LfB5_IbAAAAAMCtsjEHEHKqcB9iQocwwxTiihJu" \
--data-urlencode "pageurl=https://example.com/login" \
--data-urlencode "action=login" \
--data-urlencode "min_score=0.3" \
--data-urlencode "json=1"
A successful response contains the task ID:
{
"status": 1,
"request": "2122988149"
}
Save the request value.
It is required to retrieve the token.
Step 2: Wait before requesting the result
Wait approximately:
15–20 seconds
before sending the first result request.
Do not begin polling immediately after task creation.
Step 3: Retrieve the result
Send:
GET https://api.solvecaptcha.com/res.php
with:
key=YOUR_API_KEY
action=get
id=2122988149
json=1
Example:
curl "https://api.solvecaptcha.com/res.php?key=YOUR_API_KEY&action=get&id=2122988149&json=1"
If the task is still being processed:
{
"status": 0,
"request": "CAPCHA_NOT_READY"
}
Wait five seconds and repeat the request using the same task ID.
Do not create a duplicate task while the original one is still active.
A successful response contains the token:
{
"status": 1,
"request": "03AFcWeA5dCJ-2OQqwd0-2IHmBX3ItBl76..."
}
The value of request is the reCAPTCHA v3 token.
Step 4: Apply the token
There is no universal method for applying a reCAPTCHA v3 token.
The website may send it through:
g-recaptcha-response
g-recaptcha-response-100000
recaptchaToken
captchaToken
or another custom request parameter.
The most reliable method is:
- Open Chrome DevTools.
- Select the Network tab.
- Perform the protected action manually.
- Find the POST or XHR request sent by the page.
- Inspect its request body.
- Identify the field containing the reCAPTCHA token.
- Reproduce the same request structure.
A common HTML field is:
<textarea
name="g-recaptcha-response"
></textarea>
Example JavaScript:
const field = document.querySelector(
'[name="g-recaptcha-response"]'
);
if (field) {
field.value =
"TOKEN_FROM_SOLVECAPTCHA";
field.dispatchEvent(
new Event("input", {
bubbles: true
})
);
field.dispatchEvent(
new Event("change", {
bubbles: true
})
);
}
Some reCAPTCHA v3 integrations generate the token immediately before sending an XHR request. In that case, supplying the token directly in the request body may be more reliable than changing the page DOM.
Complete Python example
Install Requests:
python -m pip install requests
Set your API key:
export SOLVECAPTCHA_API_KEY="YOUR_API_KEY"
Create recaptcha_v3.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"
)
INITIAL_WAIT_SECONDS = 20
POLL_INTERVAL_SECONDS = 5
MAX_WAIT_SECONDS = 180
class SolveCaptchaError(RuntimeError):
"""Raised when SolveCaptcha returns an error."""
@dataclass(frozen=True)
class RecaptchaV3Solution:
task_id: str
token: str
def parse_response(
response: requests.Response,
) -> dict[str, Any]:
response.raise_for_status()
try:
result = response.json()
except requests.JSONDecodeError as exc:
raise SolveCaptchaError(
"SolveCaptcha returned invalid JSON: "
f"{response.text[:500]}"
) from exc
if not isinstance(result, dict):
raise SolveCaptchaError(
f"Unexpected response: {result!r}"
)
return result
class RecaptchaV3Client:
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 = "verify",
min_score: float = 0.3,
domain: str = "google.com",
) -> str:
if not sitekey:
raise ValueError(
"reCAPTCHA site key is required"
)
if not pageurl:
raise ValueError(
"Page URL is required"
)
if domain not in {
"google.com",
"recaptcha.net",
}:
raise ValueError(
"domain must be google.com "
"or recaptcha.net"
)
payload = {
"key": self.api_key,
"method": "userrecaptcha",
"version": "v3",
"googlekey": sitekey,
"pageurl": pageurl,
"action": action,
"min_score": min_score,
"domain": domain,
"json": 1,
}
response = self.session.post(
CREATE_TASK_URL,
data=payload,
timeout=self.request_timeout,
)
result = parse_response(response)
if result.get("status") != 1:
raise SolveCaptchaError(
"Unable to create task: "
f"{result.get('request')}"
)
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,
) -> str | 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_response(response)
if result.get("status") == 1:
token = str(
result.get("request", "")
).strip()
if not token:
raise SolveCaptchaError(
"SolveCaptcha returned "
"an empty token"
)
return token
error_code = str(
result.get(
"request",
"UNKNOWN_ERROR",
)
)
if error_code == "CAPCHA_NOT_READY":
return None
raise SolveCaptchaError(
f"Task {task_id} failed: "
f"{error_code}"
)
def solve(
self,
*,
sitekey: str,
pageurl: str,
action: str = "verify",
min_score: float = 0.3,
domain: str = "google.com",
) -> RecaptchaV3Solution:
task_id = self.create_task(
sitekey=sitekey,
pageurl=pageurl,
action=action,
min_score=min_score,
domain=domain,
)
time.sleep(
INITIAL_WAIT_SECONDS
)
deadline = (
time.monotonic()
+ MAX_WAIT_SECONDS
)
while time.monotonic() < deadline:
token = self.get_result(
task_id
)
if token is not None:
return RecaptchaV3Solution(
task_id=task_id,
token=token,
)
time.sleep(
POLL_INTERVAL_SECONDS
)
raise TimeoutError(
f"Task {task_id} was not completed "
f"within {MAX_WAIT_SECONDS} seconds"
)
def report(
self,
task_id: str,
accepted: bool,
) -> None:
action = (
"reportgood"
if accepted
else "reportbad"
)
response = self.session.get(
GET_RESULT_URL,
params={
"key": self.api_key,
"action": action,
"id": task_id,
"json": 1,
},
timeout=self.request_timeout,
)
parse_response(response)
def main() -> None:
api_key = os.environ.get(
"SOLVECAPTCHA_API_KEY",
"",
).strip()
if not api_key:
raise SystemExit(
"Set SOLVECAPTCHA_API_KEY"
)
client = RecaptchaV3Client(
api_key=api_key
)
solution = client.solve(
sitekey=(
"6LfB5_IbAAAAAMCtsjEHEHK"
"qcB9iQocwwxTiihJu"
),
pageurl=(
"https://example.com/login"
),
action="login",
min_score=0.3,
)
print(
"Task ID:",
solution.task_id,
)
print(
"Token:",
solution.token,
)
# Apply the token to the target website.
accepted = True
client.report(
task_id=solution.task_id,
accepted=accepted,
)
if __name__ == "__main__":
main()
Run the script:
python recaptcha_v3.py
PHP example
<?php
declare(strict_types=1);
const CREATE_TASK_URL =
'https://api.solvecaptcha.com/in.php';
const GET_RESULT_URL =
'https://api.solvecaptcha.com/res.php';
$apiKey = getenv('SOLVECAPTCHA_API_KEY');
if (!$apiKey) {
throw new RuntimeException(
'Set SOLVECAPTCHA_API_KEY'
);
}
function requestJson(
string $url,
array $parameters,
bool $post = false
): array {
$curl = curl_init();
if ($curl === false) {
throw new RuntimeException(
'Unable to initialize cURL'
);
}
if ($post) {
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS =>
http_build_query($parameters),
]);
} else {
curl_setopt(
$curl,
CURLOPT_URL,
$url . '?' .
http_build_query($parameters)
);
}
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$response = curl_exec($curl);
if ($response === false) {
$error = curl_error($curl);
curl_close($curl);
throw new RuntimeException(
'HTTP request failed: ' . $error
);
}
$statusCode = curl_getinfo(
$curl,
CURLINFO_RESPONSE_CODE
);
curl_close($curl);
if ($statusCode < 200 ||
$statusCode >= 300) {
throw new RuntimeException(
'Unexpected HTTP status: ' .
$statusCode
);
}
$result = json_decode(
$response,
true,
512,
JSON_THROW_ON_ERROR
);
if (!is_array($result)) {
throw new RuntimeException(
'Unexpected API response'
);
}
return $result;
}
$created = requestJson(
CREATE_TASK_URL,
[
'key' => $apiKey,
'method' => 'userrecaptcha',
'version' => 'v3',
'googlekey' =>
'6LfB5_IbAAAAAMCtsjEHEHK' .
'qcB9iQocwwxTiihJu',
'pageurl' =>
'https://example.com/login',
'action' => 'login',
'min_score' => '0.3',
'domain' => 'google.com',
'json' => '1',
],
true
);
if (($created['status'] ?? 0) !== 1) {
throw new RuntimeException(
'Task creation failed: ' .
($created['request'] ??
'UNKNOWN_ERROR')
);
}
$taskId = (string) $created['request'];
sleep(20);
$deadline = time() + 180;
$token = null;
while (time() < $deadline) {
$result = requestJson(
GET_RESULT_URL,
[
'key' => $apiKey,
'action' => 'get',
'id' => $taskId,
'json' => '1',
]
);
if (($result['status'] ?? 0) === 1) {
$token = (string) $result['request'];
break;
}
$errorCode = (string) (
$result['request'] ??
'UNKNOWN_ERROR'
);
if ($errorCode !== 'CAPCHA_NOT_READY') {
throw new RuntimeException(
'Captcha task failed: ' .
$errorCode
);
}
sleep(5);
}
if ($token === null) {
throw new RuntimeException(
'Captcha task timed out'
);
}
echo 'Task ID: ' . $taskId . PHP_EOL;
echo 'Token: ' . $token . PHP_EOL;
Reporting accepted and rejected tokens
After applying the token, report whether it was accepted.
Accepted token:
https://api.solvecaptcha.com/res.php?key=YOUR_API_KEY&action=reportgood&id=TASK_ID
Rejected token:
https://api.solvecaptcha.com/res.php?key=YOUR_API_KEY&action=reportbad&id=TASK_ID
Use reportgood when:
- the protected request succeeded;
- the form was submitted;
- the website accepted the token;
- no captcha validation error was returned.
Use reportbad only when the token itself was rejected.
Do not use reportbad when the failure was caused by:
- an incorrect site key;
- an incorrect page URL;
- the wrong action;
- an expired page;
- an integration error;
- an incorrect form field;
- a browser session change;
- application validation unrelated to captcha.
SolveCaptcha allows reports to be submitted for a limited period after task creation, so send the report immediately after determining the result.
Common errors
ERROR_WRONG_USER_KEY
The API key is invalid.
Check:
SOLVECAPTCHA_API_KEY
ERROR_ZERO_BALANCE
The account balance is insufficient.
Stop creating new tasks until the balance is replenished.
ERROR_CAPTCHA_UNSOLVABLE
The captcha could not be solved reliably.
Check:
googlekey;pageurl;version=v3;action;min_score;- the reCAPTCHA loading domain.
Do not repeatedly submit the same incorrect parameters.
CAPCHA_NOT_READY
The task is still processing.
Wait five seconds and request the result again using the same task ID.
Token rejected by the website
Possible causes include:
- incorrect action;
- incorrect site key;
- incorrect page URL;
- unsupported requested score;
- token applied to the wrong request field;
- token applied after the page state changed;
- website-specific verification requirements.
Common implementation mistakes
Using API v2 parameter names
Do not submit:
RecaptchaV3TaskProxyless
websiteURL
websiteKey
pageAction
minScore
The documented SolveCaptcha integration uses:
method=userrecaptcha
version=v3
pageurl
googlekey
action
min_score
Using createTask and getTaskResult
Use:
https://api.solvecaptcha.com/in.php
and:
https://api.solvecaptcha.com/res.php
Requesting an unrealistic score
Do not assume that requesting:
min_score=0.9
guarantees a score of 0.9.
The SolveCaptcha documentation warns that obtaining scores above 0.3 can be difficult.
Guessing the action
The action should match the value passed by the website to:
grecaptcha.execute()
Polling too early
Wait approximately 15–20 seconds before the first result request.
Polling too frequently
After receiving:
CAPCHA_NOT_READY
wait five seconds.
Applying the token only to g-recaptcha-response
Some websites use:
g-recaptcha-response-100000
or a custom request parameter.
Inspect the real network request.
Reporting every failed request as reportbad
An integration failure does not prove that the returned token was incorrect.
Frequently asked questions
Which method is used for reCAPTCHA v3?
Use:
method=userrecaptcha
version=v3
Which parameters are required?
Required parameters are:
key
method
version
googlekey
pageurl
Is action required?
No. The documentation defines it as optional and uses:
verify
as the default value.
When the website specifies an action, send the exact value.
Is min_score required?
No. The documented default is:
0.4
A lower value such as 0.3 is generally more realistic when the target website permits it.
Where can I find the site key?
Look for:
api.js?render=SITE_KEY
grecaptcha.execute("SITE_KEY")
or:
k=SITE_KEY
in a reCAPTCHA iframe URL.
Where is the token returned?
The completed JSON response contains it in:
request
How often should I request the result?
Wait 15–20 seconds before the first request. If the API returns CAPCHA_NOT_READY, repeat after five seconds.
Where should the token be submitted?
Inspect the target request. Common fields include:
g-recaptcha-response
g-recaptcha-response-100000
Does min_score guarantee acceptance?
No. The website can reject a token based on the action, page, site key, score, or application-specific checks.
Should I report results?
Yes. Use:
reportgood
for accepted tokens and:
reportbad
only for genuinely rejected solutions.
Conclusion
A reliable reCAPTCHA v3 integration requires accurate parameters rather than repeated experimentation with arbitrary scores.
The correct workflow is:
- Confirm that the page uses reCAPTCHA v3.
- Extract the site key from
api.js, an iframe, orgrecaptcha.execute(). - Find the exact action used by the website.
- Submit
method=userrecaptcha. - Set
version=v3. - Pass the site key as
googlekey. - Pass the complete page URL as
pageurl. - Use a realistic
min_score. - Wait 15–20 seconds before checking the result.
- Poll every five seconds while the task is processing.
- Apply the token through the field or request used by the website.
- Report accepted and genuinely rejected solutions.
Use the SolveCaptcha API documentation to verify the current parameters before deploying the integration.