reCAPTCHA v2 Callback Token Solving
Solve Google reCAPTCHA v2 with callback function support. Used when sites verify tokens through JavaScript callbacks instead of standard form submission.
Some websites use the data-callback attribute on the reCAPTCHA element to define a
JavaScript function that receives the solved token. Instead of submitting a form directly, the callback
function handles token verification, often making AJAX requests or triggering custom logic. This type
ensures proper callback handling and token delivery to the site's verification flow.
Captcha Type
"type": "RECAPTCHA_V2_CALLBACK_TOKEN"
Request Format
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
auth.token |
string | required | Your API key |
captcha.type |
string | required | Must be "RECAPTCHA_V2_CALLBACK_TOKEN" |
captcha.metadata.siteUrl |
string | required | URL where the callback reCAPTCHA appears |
captcha.metadata.siteKey |
string | required | reCAPTCHA site key (data-sitekey attribute) |
captcha.payload.userAgent |
string | optional | Your browser's user agent to improve solving accuracy |
captcha.payload.cookies |
array | optional | Array of cookie objects (see Cookie Object Structure below) |
captcha.payload.cookies[].name |
string | required* | Cookie name |
captcha.payload.cookies[].value |
string | required* | Cookie value |
captcha.payload.cookies[].domain |
string | required* | Cookie domain (e.g., ".example.com") |
captcha.payload.domain |
string | optional | reCAPTCHA API endpoint domain if the site uses an alternative |
captcha.payload.proxy |
object | optional | Proxy configuration object |
captcha.payload.proxy.protocol |
string | required* | Proxy protocol: "http", "https", "socks4", "socks5" |
captcha.payload.proxy.host |
string | required* | Proxy IP address |
captcha.payload.proxy.port |
number | required* | Proxy port number |
captcha.payload.proxy.username |
string | optional | Proxy authentication username |
captcha.payload.proxy.password |
string | optional | Proxy authentication password |
* Required only if parent object (proxy/cookies) is provided
Example Request
const response = await fetch('https://solver-api.mydisct.com/createTask', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'apikey': 'YOUR_API_KEY'
},
body: JSON.stringify({
auth: {
token: 'YOUR_API_KEY'
},
context: {
source: 'api',
version: '1.0.0'
},
captcha: {
type: 'RECAPTCHA_V2_CALLBACK_TOKEN',
metadata: {
siteUrl: 'https://example.com/login',
siteKey: '6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-'
},
payload: {
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...',
proxy: {
protocol: 'http',
host: '1.2.3.4',
port: 8080,
username: 'proxyuser',
password: 'proxypass'
}
}
}
})
});
const data = await response.json();
console.log('Task ID:', data.task.id);
Response Format
Create Task Response (Processing)
{
"success": true,
"service": "MyDisct Solver",
"message": "Captcha task created successfully",
"task": {
"id": "MyDisctSolver_abc123",
"status": "processing"
}
}
Fetch Result Response (Processing)
{
"success": true,
"service": "MyDisct Solver",
"message": "Captcha is being processed",
"task": {
"id": "MyDisctSolver_abc123",
"status": "processing"
}
}
Fetch Result Response (Completed)
{
"success": true,
"service": "MyDisct Solver",
"message": "Captcha solved successfully",
"task": {
"id": "MyDisctSolver_abc123",
"status": "completed",
"result": {
"token": "03AGdBq24PBCbwiDRaS_MJ7Z...",
"timestamp": "2025-12-13T12:00:00.000Z"
}
}
}
The token field contains the g-recaptcha-response value. For callback-based reCAPTCHA,
you must pass this token to the site's callback function (defined in the data-callback
attribute) instead of simply submitting a form.
Implementation Guide
Step 1: Identify Callback reCAPTCHA
// Callback reCAPTCHA has a data-callback attribute on the element
function isCallbackRecaptcha() {
const recaptchaDiv = document.querySelector('.g-recaptcha');
if (recaptchaDiv) {
return recaptchaDiv.hasAttribute('data-callback');
}
return false;
}
function getCallbackInfo() {
const recaptchaDiv = document.querySelector('.g-recaptcha, [data-sitekey]');
if (recaptchaDiv) {
return {
siteKey: recaptchaDiv.getAttribute('data-sitekey'),
callbackName: recaptchaDiv.getAttribute('data-callback')
};
}
return null;
}
const info = getCallbackInfo();
console.log('Site Key:', info?.siteKey);
console.log('Callback Function:', info?.callbackName);
Step 2: Solve Callback Token
async function solveRecaptchaV2Callback(siteUrl, siteKey) {
const createResponse = await fetch('https://solver-api.mydisct.com/createTask', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'apikey': 'YOUR_API_KEY'
},
body: JSON.stringify({
auth: { token: 'YOUR_API_KEY' },
context: { source: 'api', version: '1.0.0' },
captcha: {
type: 'RECAPTCHA_V2_CALLBACK_TOKEN',
metadata: { siteUrl, siteKey },
payload: {
userAgent: navigator.userAgent
}
}
})
});
const createData = await createResponse.json();
if (!createData.success) throw new Error(createData.error.message);
const taskId = createData.task.id;
while (true) {
await new Promise(resolve => setTimeout(resolve, 5000));
const resultResponse = await fetch('https://solver-api.mydisct.com/fetchResult', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'apikey': 'YOUR_API_KEY'
},
body: JSON.stringify({ taskId })
});
const resultData = await resultResponse.json();
if (resultData.task.status === 'completed') {
return resultData.task.result.token;
} else if (resultData.task.status === 'failed') {
throw new Error('Callback token solving failed');
}
}
}
const token = await solveRecaptchaV2Callback(
'https://example.com/login',
'6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-'
);
console.log('Callback Token:', token);
Step 3: Submit Token with Callback Trigger
// Inject token and trigger the callback function
function injectCallbackToken(token) {
// Set the g-recaptcha-response field
let responseField = document.querySelector('[name="g-recaptcha-response"]');
if (!responseField) {
responseField = document.createElement('textarea');
responseField.name = 'g-recaptcha-response';
responseField.style.display = 'none';
document.querySelector('form').appendChild(responseField);
}
responseField.value = token;
// IMPORTANT: Trigger the callback function
const recaptchaDiv = document.querySelector('.g-recaptcha');
const callbackName = recaptchaDiv?.getAttribute('data-callback');
if (callbackName && typeof window[callbackName] === 'function') {
// Call the site's callback function with the token
window[callbackName](token);
console.log('Callback triggered:', callbackName);
} else {
console.warn('Callback function not found:', callbackName);
// Fallback: try submitting the form
document.querySelector('form')?.submit();
}
}
Python Example
import requests
import time
def solve_recaptcha_v2_callback(site_url, site_key, api_key):
"""Solve reCAPTCHA v2 Callback token challenge"""
# Step 1: Create task
create_response = requests.post(
'https://solver-api.mydisct.com/createTask',
headers={
'Content-Type': 'application/json',
'apikey': api_key
},
json={
'auth': {'token': api_key},
'context': {'source': 'api', 'version': '1.0.0'},
'captcha': {
'type': 'RECAPTCHA_V2_CALLBACK_TOKEN',
'metadata': {
'siteUrl': site_url,
'siteKey': site_key
},
'payload': {}
}
}
)
create_data = create_response.json()
if not create_data['success']:
raise Exception(create_data['error']['message'])
task_id = create_data['task']['id']
print(f'Task created: {task_id}')
# Step 2: Poll for result
while True:
time.sleep(5)
result_response = requests.post(
'https://solver-api.mydisct.com/fetchResult',
headers={
'Content-Type': 'application/json',
'apikey': api_key
},
json={'taskId': task_id}
)
result_data = result_response.json()
if result_data['task']['status'] == 'completed':
return result_data['task']['result']['token']
elif result_data['task']['status'] == 'failed':
raise Exception('Callback token solving failed')
print('Waiting for solution...')
# Example usage
token = solve_recaptcha_v2_callback(
site_url='https://example.com/login',
site_key='6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-',
api_key='YOUR_API_KEY'
)
print(f'Callback Token: {token}')
# Submit with form (callback sites often use AJAX)
response = requests.post(
'https://example.com/verify',
json={
'email': '[email protected]',
'password': 'securepassword',
'g-recaptcha-response': token
}
)
print(f'Verify response: {response.status_code}')
Best Practices
- Identify Callback Function: Always check the
data-callbackattribute to find the correct function name - Trigger Callback: After injecting the token, you must call the callback function - simply setting the form field is not enough
- User Agent: Include a realistic user agent string for better success rates
- Polling Intervals: Use 5-second polling intervals for optimal performance
- Token Expiration: Tokens expire after ~2 minutes, trigger the callback immediately
- Callback Verification: Verify the callback function exists before calling it to avoid errors
Common Issues
Solution: Make sure you're calling the correct callback function after token
injection. Check the data-callback attribute on the reCAPTCHA element and ensure the
function is available in the global scope (window[callbackName]).
Solution: Some sites define callbacks dynamically or use nested function references.
Inspect the page source carefully for the actual callback function. If the standard
data-callback approach doesn't work, check for programmatic reCAPTCHA rendering with
custom callback parameters.