reCAPTCHA v2 Token Solving
Solve Google reCAPTCHA v2 checkbox captchas. Returns verification token for form submission. For invisible reCAPTCHA v2, use the dedicated RECAPTCHA_V2_INVISIBLE_TOKEN type.
Google reCAPTCHA v2 is the most widely used captcha service on the internet. The checkbox variant requires users to click "I'm not a robot". This service generates valid verification tokens without requiring user interaction, allowing you to automate form submissions. For invisible reCAPTCHA v2, please use the RECAPTCHA_V2_INVISIBLE_TOKEN type instead.
Captcha Type
"type": "RECAPTCHA_V2_TOKEN"
Request Format
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
captcha.type |
string | required | Must be "RECAPTCHA_V2_TOKEN" |
captcha.metadata.siteUrl |
string | required | URL where captcha appears |
captcha.metadata.siteKey |
string | required | reCAPTCHA site key (data-sitekey) |
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.cookies[].path |
string | optional | Cookie path (defaults to "/") |
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 proxy object 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_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...', // Your browser UA
cookies: [
{ name: 'session_id', value: 'abc123', domain: '.example.com' },
{ name: 'auth_token', value: 'xyz789', domain: '.example.com' }
],
domain: 'google.com', // Alternative API domain if used by site
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 is being processed",
"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": "03AGdBq27QF...",
"timestamp": "2025-11-05T12:34:56.789Z"
}
}
}
The token field contains the g-recaptcha-response value. Submit this token in the
g-recaptcha-response form field or use it in your API requests.
Implementation Guide
Step 1: Extract reCAPTCHA Site Key
First, find the reCAPTCHA site key from the page:
// Method 1: From script tag
function getRecaptchaSiteKey() {
const scripts = document.querySelectorAll('script');
for (const script of scripts) {
const match = script.src?.match(/recaptcha/api.js?render=([^&]+)/);
if (match) return match[1];
}
const recaptchaDiv = document.querySelector('.g-recaptcha, [data-sitekey]');
if (recaptchaDiv) {
return recaptchaDiv.getAttribute('data-sitekey') ||
recaptchaDiv.getAttribute('data-sitekey-v2') ||
recaptchaDiv.getAttribute('data-sitekey-v3');
}
if (window.grecaptcha && window.grecaptcha.render) {
const widgets = document.querySelectorAll('.g-recaptcha');
if (widgets.length > 0) {
return widgets[0].getAttribute('data-sitekey');
}
}
return null;
}
const siteKey = getRecaptchaSiteKey();
console.log('Site Key:', siteKey);
Step 2: Solve reCAPTCHA Token
async function solveRecaptchaV2Token(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_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)); // Wait 5 seconds
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('Token solving failed');
}
}
}
const token = await solveRecaptchaV2Token(
'https://example.com/login',
'6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-'
);
console.log('reCAPTCHA Token:', token);
Step 3: Submit Token with Form
// Method 1: Submit with form data
async function submitFormWithToken(token) {
const formData = new FormData();
formData.append('username', 'myusername');
formData.append('password', 'mypassword');
formData.append('g-recaptcha-response', token);
const response = await fetch('https://example.com/login', {
method: 'POST',
body: formData
});
return await response.json();
}
async function submitJsonWithToken(token) {
const response = await fetch('https://example.com/api/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: 'myusername',
password: 'mypassword',
'g-recaptcha-response': token
})
});
return await response.json();
}
function injectTokenIntoForm(token) {
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;
document.querySelector('form').submit();
}
const token = await solveRecaptchaV2Token(siteUrl, siteKey);
await submitFormWithToken(token);
Python Example
import requests
import time
def solve_recaptcha_v2_token(site_url, site_key, api_key):
"""
Solve reCAPTCHA v2 token challenge
Args:
site_url: URL where captcha appears
site_key: reCAPTCHA site key
api_key: Your MyDisct Solver API key
Returns:
reCAPTCHA response token
"""
# 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_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) # Wait 5 seconds
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('Token solving failed')
print('Waiting for solution...')
# Example usage
token = solve_recaptcha_v2_token(
site_url='https://example.com/login',
site_key='6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-',
api_key='YOUR_API_KEY'
)
print(f'reCAPTCHA Token: {token}')
# Submit with form
response = requests.post(
'https://example.com/login',
data={
'username': 'myusername',
'password': 'mypassword',
'g-recaptcha-response': token
}
)
print(f'Login response: {response.status_code}')
Best Practices
- Always use the exact site URL where the captcha appears
- Include user agent for better success rates
- Poll every 5 seconds for token-based captchas (they take longer than image captchas)
- Cache tokens for a short period if making multiple requests
- Handle token expiration (tokens typically expire after 2 minutes)
- Use proxy if required by the target website
- Implement proper error handling for failed tasks
Common Issues
Solution: Ensure you're using the correct site key and site URL. The URL must match exactly where the captcha is displayed.
Solution: reCAPTCHA tokens expire after ~2 minutes. Request a new token if submission takes too long.
Solution: If the site uses invisible reCAPTCHA v2, use the dedicated RECAPTCHA_V2_INVISIBLE_TOKEN type instead.