hCaptcha Image Solving
Solve hCaptcha image challenges programmatically with our AI-powered API. hCaptcha presents users with a grid of images and asks them to select specific objects. Our service analyzes these images and returns the correct selections with 99.8% accuracy.
hCaptcha is a popular captcha service that displays a 3x3 grid of images and asks users to identify images containing specific objects (e.g., "Select all images with traffic lights"). Our API processes these images and returns the indices of correct selections.
Captcha Type
Use the following captcha type identifier in your API requests:
"type": "HCAPTCHA_IMAGE"
Request Format
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
auth.token |
string | required | Your API key |
captcha.type |
string | required | Must be "HCAPTCHA_IMAGE" |
captcha.metadata.siteUrl |
string | required | The URL where the captcha appears |
captcha.metadata.siteKey |
string | optional | hCaptcha site key (if available) |
captcha.payload.images |
array | required | Array of base64-encoded images (9 images for 3x3 grid) |
captcha.payload.question |
string | required | The question text (e.g., "Select all images with cars") |
captcha.payload.referenceImages |
array | optional | Reference images shown above the grid (if any) |
captcha.payload.questionType |
string | optional | Challenge type: "grid" (default), "multi", "click", or "drag" |
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: 'HCAPTCHA_IMAGE',
metadata: {
siteUrl: 'https://example.com',
siteKey: 'a5f74b19-9e45-40e0-b45d-47ff91b7a6c2'
},
payload: {
images: [
'/9j/4AAQSkZJRgABAQAAAQABAAD...', // Base64 image 1
'/9j/4AAQSkZJRgABAQAAAQABAAD...', // Base64 image 2
'/9j/4AAQSkZJRgABAQAAAQABAAD...', // Base64 image 3
'/9j/4AAQSkZJRgABAQAAAQABAAD...', // Base64 image 4
'/9j/4AAQSkZJRgABAQAAAQABAAD...', // Base64 image 5
'/9j/4AAQSkZJRgABAQAAAQABAAD...', // Base64 image 6
'/9j/4AAQSkZJRgABAQAAAQABAAD...', // Base64 image 7
'/9j/4AAQSkZJRgABAQAAAQABAAD...', // Base64 image 8
'/9j/4AAQSkZJRgABAQAAAQABAAD...' // Base64 image 9
],
question: 'Select all images with traffic lights',
referenceImages: [],
questionType: 'grid' // or 'multi', 'click', 'drag'
}
}
})
});
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_abc123def456",
"status": "processing"
}
}
Fetch Result Response (Processing)
{
"success": true,
"service": "MyDisct Solver",
"message": "Captcha is being processed",
"task": {
"id": "MyDisctSolver_abc123def456",
"status": "processing"
}
}
Fetch Result Response (Completed)
{
"success": true,
"service": "MyDisct Solver",
"message": "Captcha solved successfully",
"task": {
"id": "MyDisctSolver_abc123def456",
"status": "completed",
"result": {
"answers": [0, 2, 5, 7],
"timestamp": "2025-11-05T12:34:56.789Z"
}
}
}
The answers array contains the indices of images that should be selected.
Indices start from 0 (top-left) and go to 8 (bottom-right) in a 3x3 grid.
In the example above, images at positions 0, 2, 5, and 7 contain traffic lights.
Implementation Guide
Step 1: Extract Images from hCaptcha
First, you need to extract the images from the hCaptcha challenge. Here's how to do it using JavaScript:
// Extract images from hCaptcha iframe
function extractHCaptchaImages() {
const iframe = document.querySelector('iframe[src*="hcaptcha.com"]');
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
const question = iframeDoc.querySelector('.prompt-text').textContent;
const imageElements = iframeDoc.querySelectorAll('.task-image .image');
const images = [];
for (const img of imageElements) {
const bgImage = img.style.backgroundImage;
const imageUrl = bgImage.slice(5, -2); // Remove url(" and ")
fetch(imageUrl)
.then(res => res.blob())
.then(blob => {
const reader = new FileReader();
reader.onloadend = () => {
const base64 = reader.result.split(',')[1];
images.push(base64);
};
reader.readAsDataURL(blob);
});
}
return { question, images };
}
Step 2: Send to API and Poll for Result
async function solveHCaptcha(images, question, 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: 'HCAPTCHA_IMAGE',
metadata: { siteUrl, siteKey },
payload: { images, question, questionType: 'grid' }
}
})
});
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, 3000)); // Wait 3 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.answers;
} else if (resultData.task.status === 'failed') {
throw new Error('Captcha solving failed');
}
}
}
const { images, question } = extractHCaptchaImages();
const solution = await solveHCaptcha(
images,
question,
'https://example.com',
'a5f74b19-9e45-40e0-b45d-47ff91b7a6c2'
);
console.log('Solution:', solution); // [0, 2, 5, 7]
Step 3: Apply Solution to hCaptcha
function applyHCaptchaSolution(solution) {
const iframe = document.querySelector('iframe[src*="hcaptcha.com"]');
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
const imageElements = iframeDoc.querySelectorAll('.task-image .image');
solution.forEach(index => {
imageElements[index].click();
});
iframeDoc.querySelector('.button-submit').click();
}
applyHCaptchaSolution(solution);
Python Example
import requests
import time
import base64
def solve_hcaptcha(images, question, site_url, site_key, api_key):
"""
Solve hCaptcha image challenge
Args:
images: List of base64-encoded images
question: Question text
site_url: URL where captcha appears
site_key: hCaptcha site key
api_key: Your MyDisct Solver API key
Returns:
List of indices for correct images
"""
# 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': 'HCAPTCHA_IMAGE',
'metadata': {
'siteUrl': site_url,
'siteKey': site_key
},
'payload': {
'images': images,
'question': question,
'questionType': 'grid'
}
}
}
)
create_data = create_response.json()
if not create_data['success']:
raise Exception(create_data['error']['message'])
task_id = create_data['task']['id']
# Step 2: Poll for result
while True:
time.sleep(3) # Wait 3 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']['answers']
elif result_data['task']['status'] == 'failed':
raise Exception('Captcha solving failed')
# Example usage
images = [
'base64_image_1',
'base64_image_2',
# ... 9 images total
]
solution = solve_hcaptcha(
images=images,
question='Select all images with traffic lights',
site_url='https://example.com',
site_key='a5f74b19-9e45-40e0-b45d-47ff91b7a6c2',
api_key='YOUR_API_KEY'
)
print(f'Solution: {solution}') # [0, 2, 5, 7]
Best Practices
- Always include the exact question text as it appears in the captcha
- Ensure images are properly base64-encoded without data URI prefix
- Poll for results every 3-5 seconds to avoid rate limiting
- Implement proper error handling for failed tasks
- Cache the site key if it doesn't change frequently
- Use reference images when available for better accuracy
Common Issues
Solution: Ensure images are properly base64-encoded and in the correct order (left-to-right, top-to-bottom).
Solution: Verify the question text matches exactly what's shown in the captcha. Even small differences can affect accuracy.
Solution: Increase polling interval or check if images are too large. Consider compressing images before sending.