Error Handling
Learn how to properly handle errors in the MyDisct Solver API. Understanding error responses and implementing robust error handling is crucial for building reliable applications.
Error Response Format
All error responses follow a consistent format:
{
"success": false,
"service": "MyDisct Solver",
"message": "Brief error description",
"error": {
"code": 400,
"message": "Detailed error message"
}
}
Error Response Fields
| Field | Type | Description |
|---|---|---|
success |
boolean | Always false for error responses |
service |
string | Always "MyDisct Solver" |
message |
string | Brief error description |
error.code |
number | HTTP status code (400, 401, 402, 403, 404, 500, 503, 504) |
error.message |
string | Detailed error message with context |
HTTP Status Codes & Error Messages
Authentication Errors (401, 403)
| HTTP Status | Error Code | Message | Description |
|---|---|---|---|
| 401 | API_KEY_REQUIRED | API Key is required | No API key provided in headers (x-api-key or apikey) |
| 403 | INVALID_API_KEY | Invalid or inactive API Key | API key is invalid or account is not active |
| 403 | ACCOUNT_SUSPENDED | Your account has been suspended | Account is suspended due to policy violations. Contact support for more information. |
| 403 | ACCOUNT_INACTIVE | Your account is inactive | Account needs activation or reactivation. Contact support to activate your account. |
| 500 | API_KEY_VALIDATION_ERROR | Error during API Key validation | Internal error while validating API key |
Balance Errors (402)
| HTTP Status | Error Code | Message | Description |
|---|---|---|---|
| 402 | INSUFFICIENT_BALANCE | Insufficient balance | Account balance is too low to create this task. Add funds to continue. |
Request Validation Errors (400)
| HTTP Status | Error Code | Message | Common Causes |
|---|---|---|---|
| 400 | INVALID_REQUEST | Invalid request body format | Request body is not valid JSON or missing |
| 400 | CAPTCHA_TYPE_REQUIRED | Captcha type is required | captcha.type field is missing |
| 400 | UNSUPPORTED_CAPTCHA_TYPE | Invalid or unsupported captcha type | captcha.type is not in the supported list |
Missing Field Errors (400)
| Error Code | Message | Description |
|---|---|---|
MISSING_SITE_URL |
Missing required field: siteUrl | The website URL where the captcha appears is missing. Required for most captcha types. |
MISSING_SITE_KEY |
Missing required field: siteKey | The captcha site key from the website is missing. Required for hCaptcha, reCAPTCHA, etc. |
MISSING_IMAGES |
Missing required field: images | Captcha images array is missing or empty. Required for all image-based captchas. |
MISSING_QUESTION |
Missing required field: question | The captcha question text is missing. Required for grid captchas and PopularCaptcha variants. |
MISSING_QUESTION_TYPE |
Missing required field: questionType | The captcha question type is missing. Required for hCaptcha, GeeTest, TikTok, and others. |
MISSING_CAPTCHA_ID |
Missing required field: captchaId | The captcha identifier is missing. Required for Lemin Captcha. |
MISSING_WEBSITE_PUBLIC_KEY |
Missing required field: websitePublicKey | The FunCaptcha public key is missing. Required for FunCaptcha solving. |
MISSING_REFERENCE_IMAGES |
Missing required field: referenceImages | Reference images for comparison are missing. Required for GeeTest v3 slide/click captchas. |
Invalid Field Errors (400)
| Error Code | Message | Description |
|---|---|---|
INVALID_IMAGE_COUNT |
Invalid number of images | Wrong number of images provided. Example: Temu requires exactly 4 images, Shopee requires 2. |
INVALID_QUESTION_TYPE |
Invalid questionType | The questionType value is not valid for this captcha type. |
INVALID_PROXY_FORMAT |
Invalid proxy format | Proxy object is missing required fields (protocol, host, port). |
INVALID_ARRAY_FORMAT |
Invalid array format | Expected an array but received a different data type. |
Data Quality Errors (400)
| Error Code | Message | Description |
|---|---|---|
EMPTY_FIELD_VALUE |
Field value cannot be empty | A required field contains an empty string or whitespace only. All fields must have valid content. |
EMPTY_ARRAY_ELEMENTS |
Array contains empty elements | One or more elements in an array (like images) are empty strings. All array elements must be valid. |
INVALID_URL_FORMAT |
Invalid URL format | The URL format is invalid. URLs must start with http:// or https:// |
INVALID_BASE64_FORMAT |
Invalid base64 format | Image data is not valid base64 encoded. Images must be base64 strings or data URIs. |
IMAGE_TOO_LARGE |
Image size exceeds maximum limit | One or more images exceed the maximum allowed size. Use smaller images. |
INVALID_DATA_TYPE |
Invalid data type | A field has the wrong data type (e.g., number instead of string). Check field type requirements. |
Proxy Validation Errors (400)
| Error Code | Message | Description |
|---|---|---|
MISSING_PROXY_PROTOCOL |
Missing proxy protocol | Proxy object is missing the protocol field. Must include protocol (http, https, or socks5). |
MISSING_PROXY_HOST |
Missing proxy host | Proxy object is missing the host field. Must include host (IP address or hostname). |
MISSING_PROXY_PORT |
Missing proxy port | Proxy object is missing the port field. Must include port number. |
INVALID_PROXY_PORT |
Invalid proxy port | Proxy port is invalid. Port must be a number between 1 and 65535. |
INVALID_PROXY_PROTOCOL |
Invalid proxy protocol | Proxy protocol is invalid. Supported protocols: http, https, socks5. |
Task Errors (400, 404)
| HTTP Status | Error Code | Message | Description |
|---|---|---|---|
| 400 | TASK_ID_REQUIRED | TaskId parameter is required | taskId is missing in fetchResult request |
| 404 | TASK_NOT_FOUND | Task not found or does not belong to this user | Task ID doesn't exist or belongs to another user |
| 400 | TASK_FAILED | Task failed | Task status is 'failed' - check error_message for details |
Server Errors (500, 503, 504)
| HTTP Status | Error Code | Message | Description | Retryable |
|---|---|---|---|---|
| 500 | SERVICE_ERROR | Internal server error | Unexpected server error occurred | Yes |
| 500 | SERVICE_ERROR | Failed to parse cached response | Error parsing stored task response | No |
| 503 | SERVICE_UNAVAILABLE | MyDisct Solver service is temporarily unavailable | Service is down or overloaded | Yes |
| 504 | SERVICE_TIMEOUT | Request timeout - please try again | Request took too long to complete | Yes |
| 400 | INCORRECT_CAPTCHA_SOLUTION | The provided solution was rejected by the target website | Captcha solution was incorrect. Balance automatically refunded. | Yes |
All MyDisct Solver error responses follow a consistent format with error.code containing a string error code.
Use the error.code field to identify the specific error type and the error.message field for user-friendly error messages.
Real Error Response Examples
Missing API Key (401)
{
"success": false,
"service": "MyDisct Solver",
"error": {
"code": "API_KEY_REQUIRED",
"message": "API Key is required. Please provide it in the header as x-api-key or apikey."
}
}
Invalid API Key (403)
{
"success": false,
"service": "MyDisct Solver",
"error": {
"code": "INVALID_API_KEY",
"message": "Invalid or inactive API Key. Please check your credentials."
}
}
Account Suspended (403)
{
"success": false,
"service": "MyDisct Solver",
"error": {
"code": "ACCOUNT_SUSPENDED",
"message": "Your account has been suspended. Please contact support for more information."
}
}
Account Inactive (403)
{
"success": false,
"service": "MyDisct Solver",
"error": {
"code": "ACCOUNT_INACTIVE",
"message": "Your account is inactive. Please activate your account or contact support."
}
}
Insufficient Balance (402)
{
"success": false,
"service": "MyDisct Solver",
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "Insufficient balance"
},
"required": 0.002,
"current_balance": 0.001
}
Invalid Request Format (400)
{
"success": false,
"service": "MyDisct Solver",
"error": {
"code": "INVALID_REQUEST",
"message": "Invalid request body format"
}
}
Missing Required Field (400)
{
"success": false,
"service": "MyDisct Solver",
"error": {
"code": "MISSING_REQUIRED_FIELD",
"message": "Missing required field: siteKey"
}
}
Missing Required Field (400)
{
"success": false,
"service": "MyDisct Solver",
"error": {
"code": "MISSING_SITE_URL",
"message": "Missing required field: siteUrl. Please provide the website URL where the captcha appears."
}
}
Empty Field Value (400)
{
"success": false,
"service": "MyDisct Solver",
"error": {
"code": "EMPTY_FIELD_VALUE",
"message": "siteUrl cannot be empty"
}
}
Invalid URL Format (400)
{
"success": false,
"service": "MyDisct Solver",
"error": {
"code": "INVALID_URL_FORMAT",
"message": "Invalid URL format. URL must start with http:// or https://"
}
}
Empty Array Elements (400)
{
"success": false,
"service": "MyDisct Solver",
"error": {
"code": "EMPTY_ARRAY_ELEMENTS",
"message": "images array contains empty elements"
}
}
Invalid Image Count (400)
{
"success": false,
"service": "MyDisct Solver",
"error": {
"code": "INVALID_IMAGE_COUNT",
"message": "Temu captcha requires exactly 4 images, received 2"
}
}
Missing Proxy Field (400)
{
"success": false,
"service": "MyDisct Solver",
"error": {
"code": "MISSING_PROXY_PORT",
"message": "Missing proxy port. Proxy must include port field (1-65535)."
}
}
Invalid Proxy Port (400)
{
"success": false,
"service": "MyDisct Solver",
"error": {
"code": "INVALID_PROXY_PORT",
"message": "Invalid proxy port: 99999. Must be between 1-65535"
}
}
Invalid Data Type (400)
{
"success": false,
"service": "MyDisct Solver",
"error": {
"code": "INVALID_DATA_TYPE",
"message": "siteKey must be a string"
}
}
Task Not Found (404)
{
"success": false,
"service": "MyDisct Solver",
"error": {
"code": "TASK_NOT_FOUND",
"message": "Task not found or does not belong to this user"
}
}
Incorrect Captcha Solution (400)
{
"success": false,
"service": "MyDisct Solver",
"error": {
"code": "INCORRECT_CAPTCHA_SOLUTION",
"message": "The provided solution was rejected by the target website. Your balance has been refunded. Please request a new captcha and try again."
}
}
When you receive an INCORRECT_CAPTCHA_SOLUTION error, your account balance is automatically refunded.
This error indicates that the captcha solution was rejected by the target website, not by our service.
You can immediately request a new captcha without any additional charge.
Internal Server Error (500)
{
"success": false,
"service": "MyDisct Solver",
"error": {
"code": "SERVICE_ERROR",
"message": "Internal server error"
}
}
Request Timeout (504)
{
"success": false,
"service": "MyDisct Solver",
"error": {
"code": "SERVICE_TIMEOUT",
"message": "Request timeout - please try again"
}
}
Validation Error Guide
MyDisct Solver performs comprehensive validation on all incoming requests to ensure data quality and catch errors early. Understanding these validations will help you prevent errors before they occur.
Validation Layers
- Structure Validation: Ensures all required objects and fields are present
- Format Validation: Validates data formats (URLs, base64, arrays, objects)
- Content Validation: Checks data quality (non-empty strings, valid ranges, correct types)
Common Validation Scenarios
URL Validation
All URL fields (siteUrl, websiteURL) must:
-
Start with
http://orhttps:// - Not be empty or whitespace only
- Be properly formatted (no spaces, valid characters)
// ✅ Valid URLs
"https://example.com"
"http://subdomain.example.com/path"
"https://example.com:8080/captcha"
"example.com" // Missing protocol
"" // Empty string
" " // Whitespace only
"ftp://example.com" // Wrong protocol
Image Array Validation
Image arrays must:
- Be a valid array (not null, undefined, or other types)
- Contain at least one element (unless specific count required)
- Have no empty string elements
- Meet exact count requirements (Temu: 4 images, Shopee: 2 images)
// ✅ Valid image arrays
["base64string1", "base64string2"]
["data:image/png;base64,iVBORw0KG..."]
[] // Empty array (for types requiring images)
["image1", "", "image3"] // Contains empty element
["image1", " ", "image3"] // Contains whitespace-only element
"not-an-array" // Wrong type
null // Null value
Proxy Validation
Proxy objects must include all required fields with valid values:
| Field | Type | Valid Values | Example |
|---|---|---|---|
protocol |
string | http, https, socks5 | "http" |
host |
string | IP address or hostname (non-empty) | "proxy.example.com" or "192.168.1.1" |
port |
number | 1 - 65535 | 8080 |
username |
string | Optional - any non-empty string | "user123" |
password |
string | Optional - any string | "pass123" |
// ✅ Valid proxy
{
"protocol": "http",
"host": "proxy.example.com",
"port": 8080,
"username": "user",
"password": "pass"
}
{
"host": "proxy.example.com",
"port": 8080
}
{
"protocol": "ftp", // Invalid protocol
"host": "proxy.example.com",
"port": 8080
}
{
"protocol": "http",
"host": "", // Empty host
"port": 8080
}
{
"protocol": "http",
"host": "proxy.example.com",
"port": 99999 // Port out of range
}
Data Type Validation
All fields must have the correct data type:
// ✅ Correct types
{
"siteUrl": "https://example.com", // string
"siteKey": "abc123", // string
"images": ["base64..."], // array
"questionType": "grid", // string
"proxy": { "protocol": "http", ... } // object
}
{
"siteUrl": 12345, // number instead of string
"siteKey": ["key"], // array instead of string
"images": "single-image", // string instead of array
"questionType": null, // null instead of string
"proxy": "http://proxy:80" // string instead of object
}
Captcha-Specific Validations
| Captcha Type | Special Requirements |
|---|---|
TEMU_CAPTCHA_IMAGE |
Must have exactly 4 images (body + 3 parts) |
SHOPEE_IMAGE |
Must have exactly 2 images (puzzle piece + background) |
GEETEST_V3_IMAGE (click) |
Must have exactly 3 reference images |
HCAPTCHA_IMAGE (grid) |
Must include question field when questionType is "grid" |
GEETEST_V4_TOKEN |
Proxy is required with all fields validated |
CLOUDFLARE_CHALLENGE_TOKEN |
Requires body (base64 HTML) and validated proxy |
FUNCAPTCHA_IMAGE |
Requires websitePublicKey instead of siteKey |
BINANCE_IMAGE |
siteKey field represents bncUuid |
Always validate your data on the client side before sending requests to the API. This will reduce errors, improve response times, and provide better user experience. Use the validation rules above to implement client-side validation that matches our server-side validation.
Implementation Examples
JavaScript Error Handling
async function solveCaptchaWithErrorHandling(captchaData) {
const MAX_RETRIES = 3;
let retryCount = 0;
while (retryCount < MAX_RETRIES) {
try {
const response = await fetch('https://solver-api.mydisct.com/createTask', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'apikey': API_KEY
},
body: JSON.stringify(captchaData)
});
const data = await response.json();
if (!data.success) {
const httpStatus = response.status;
const errorMessage = data.message || data.error?.message || 'Unknown error';
if (httpStatus === 401) {
throw new Error(`API key required: ${errorMessage}`);
}
if (httpStatus === 403) {
if (errorMessage.includes('suspended') || errorMessage.includes('SUSPENDED')) {
throw new Error('Your account has been suspended. Please contact support.');
}
if (errorMessage.includes('inactive') || errorMessage.includes('INACTIVE')) {
throw new Error('Your account is inactive. Please activate your account.');
}
throw new Error(`Authentication error: ${errorMessage}`);
}
if (httpStatus === 402) {
throw new Error(`Insufficient balance. Please add funds to your account.`);
}
if (httpStatus === 400) {
throw new Error(`Invalid request: ${errorMessage}`);
}
if (httpStatus === 404) {
throw new Error(`Task not found: ${errorMessage}`);
}
if (httpStatus === 429) {
if (retryCount < MAX_RETRIES) {
const waitTime = 60; // Wait 60 seconds
console.log(`Rate limit exceeded. Waiting ${waitTime} seconds...`);
await new Promise(resolve => setTimeout(resolve, waitTime * 1000));
retryCount++;
continue;
}
throw new Error('Rate limit exceeded. Please try again later.');
}
if (httpStatus >= 500) {
if (retryCount < MAX_RETRIES) {
console.log(`Server error. Retrying... (attempt ${retryCount + 1}/${MAX_RETRIES})`);
await new Promise(resolve => setTimeout(resolve, 5000));
retryCount++;
continue;
}
throw new Error(`Server error: ${errorMessage}`);
}
throw new Error(`API error: ${errorMessage}`);
}
return data.task.id;
} catch (error) {
if (retryCount >= MAX_RETRIES - 1) {
throw error;
}
retryCount++;
}
}
}
try {
const taskId = await solveCaptchaWithErrorHandling(captchaData);
console.log('Task created:', taskId);
} catch (error) {
console.error('Failed to create task:', error.message);
}
Python Error Handling
import requests
import time
class CaptchaSolverError(Exception):
"""Base exception for captcha solver errors"""
pass
class InsufficientBalanceError(CaptchaSolverError):
"""Raised when account balance is too low"""
pass
class RateLimitError(CaptchaSolverError):
"""Raised when rate limit is exceeded"""
def __init__(self, message, retry_after=None):
super().__init__(message)
self.retry_after = retry_after
def solve_captcha_with_error_handling(captcha_data, api_key, max_retries=3):
"""
Solve captcha with comprehensive error handling
Args:
captcha_data: Captcha task data
api_key: API key
max_retries: Maximum number of retry attempts
Returns:
Task ID string
Raises:
CaptchaSolverError: For various error conditions
"""
retry_count = 0
while retry_count < max_retries:
try:
response = requests.post(
'https://solver-api.mydisct.com/createTask',
headers={
'Content-Type': 'application/json',
'apikey': api_key
},
json=captcha_data,
timeout=30
)
data = response.json()
http_status = response.status_code
# Check for errors
if not data.get('success'):
error_message = data.get('message') or data.get('error', {}).get('message', 'Unknown error')
# Handle specific HTTP status codes
if http_status == 401:
# API key missing - don't retry
raise CaptchaSolverError(f'API key required: {error_message}')
elif http_status == 403:
# Authentication/account errors - don't retry
if 'suspended' in error_message.lower() or 'SUSPENDED' in error_message:
raise CaptchaSolverError('Your account has been suspended. Please contact support.')
elif 'inactive' in error_message.lower() or 'INACTIVE' in error_message:
raise CaptchaSolverError('Your account is inactive. Please activate your account.')
else:
# Other 403 errors (invalid API key)
raise CaptchaSolverError(f'Authentication error: {error_message}')
elif http_status == 402:
# Insufficient balance - don't retry
raise InsufficientBalanceError('Insufficient balance. Please add funds.')
elif http_status == 400:
# Bad request - don't retry
raise CaptchaSolverError(f'Invalid request: {error_message}')
elif http_status == 404:
# Not found - don't retry
raise CaptchaSolverError(f'Task not found: {error_message}')
elif http_status == 429:
# Rate limit - retry with backoff
if retry_count < max_retries:
wait_time = 60 # Wait 60 seconds
print(f'Rate limit exceeded. Waiting {wait_time} seconds...')
time.sleep(wait_time)
retry_count += 1
continue
raise RateLimitError('Rate limit exceeded', 60)
elif http_status >= 500:
# Server errors - retry
if retry_count < max_retries:
print(f'Server error. Retrying... (attempt {retry_count + 1}/{max_retries})')
time.sleep(5)
retry_count += 1
continue
raise CaptchaSolverError(f'Server error: {error_message}')
else:
# Other errors
raise CaptchaSolverError(f'API error: {error_message}')
# Success - return task ID
return data['task']['id']
except requests.exceptions.Timeout:
if retry_count >= max_retries - 1:
raise CaptchaSolverError('Request timeout')
retry_count += 1
time.sleep(5)
except requests.exceptions.RequestException as e:
if retry_count >= max_retries - 1:
raise CaptchaSolverError(f'Network error: {str(e)}')
retry_count += 1
time.sleep(5)
# Usage
try:
task_id = solve_captcha_with_error_handling(captcha_data, API_KEY)
print(f'Task created: {task_id}')
except InsufficientBalanceError as e:
print(f'Balance error: {e}')
# Redirect user to add balance
except RateLimitError as e:
print(f'Rate limit error: {e}')
if e.retry_after:
print(f'Retry after {e.retry_after} seconds')
except CaptchaSolverError as e:
print(f'Solver error: {e}')
# Handle error appropriately
Best Practices
- Always check the
successfield before processing the response - Implement exponential backoff for retryable errors
- Log errors with sufficient context for debugging
- Handle rate limits gracefully with appropriate wait times
- Provide user-friendly error messages in your application
- Monitor error rates and set up alerts for critical errors
- Implement circuit breakers for repeated failures
- Cache successful responses when appropriate
Retry Strategy
Implement a smart retry strategy for handling transient errors:
async function retryWithExponentialBackoff(fn, maxRetries = 3) {
let retryCount = 0;
let delay = 1000; // Start with 1 second
while (retryCount < maxRetries) {
try {
return await fn();
} catch (error) {
if (error.retryable === false) {
throw error;
}
retryCount++;
if (retryCount >= maxRetries) {
throw error;
}
const jitter = Math.random() * 1000;
const waitTime = delay + jitter;
console.log(`Retry ${retryCount}/${maxRetries} after ${Math.round(waitTime)}ms`);
await new Promise(resolve => setTimeout(resolve, waitTime));
delay *= 2;
}
}
}
const result = await retryWithExponentialBackoff(async () => {
return await createCaptchaTask(captchaData);
});