Skip to content

Error Codes Reference Fresh

DataForSEO uses two layers of error reporting: HTTP status codes at the transport level, and DataForSEO-specific status codes inside the JSON response body.

HTTP Status Codes

CodeMeaningMost Common CauseFix
200OKRequest processedCheck the body's status_code for task-level errors
400Bad RequestMalformed JSON, missing required fieldValidate your payload structure
401UnauthorizedWrong credentialsRecheck login/password from the dashboard
403ForbiddenAccount suspended or feature not enabledCheck account status
404Not FoundWrong endpoint URLCheck the endpoint path against the reference
429Too Many RequestsRate limit hitAdd delays between requests; check /appendix/user/data
500Internal Server ErrorDataForSEO server issueRetry after 60 seconds; contact support if persistent
503Service UnavailableMaintenance or overloadRetry with exponential backoff

DataForSEO Status Codes

These appear inside the JSON response body, at both the response level and the individual task level. Always check both.

Success Codes

CodeMeaningNotes
20000OKRequest successful
20100Task createdTask accepted for processing (task-based endpoints)

Client Error Codes (4xxxx)

CodeMeaningCommon CauseFix
40000Bad requestGeneric bad requestInspect the status_message field for details
40001Authentication requiredNo credentials sentInclude Authorization header
40002Insufficient creditsAccount balance too lowAdd credits to account
40004Request entity too largePayload exceeds size limitSplit into smaller batches
40005Not foundResource ID doesn't existCheck task ID; task may have expired (30 day TTL)
40010Item not foundNo results for the queryNormal for rare keywords; not an error
40100Bad tokenInvalid auth credentialsVerify login and password are correct
40101Access deniedAccount lacks permission for this endpointCheck plan includes this API section
40102IP blockedYour IP is rate-limited or blockedRotate IPs or contact support
40200Invalid fieldWrong field name or valueCheck field names against API docs
40201Missing required fieldPayload is missing a required keyCheck the required fields for this endpoint
40202Invalid valueField value is out of valid rangeCheck min/max values (e.g., depth cannot exceed 700)
40400Task expiredTask result older than 30 daysRe-run the task
40401Task in progressTask not yet completePoll tasks_ready before fetching with task_get
40500Too many tasksBatch size exceeds limitLimit to 100 tasks per request
40600Duplicate taskSame task already submittedDataForSEO deduplicates within a short window

Server Error Codes (5xxxx)

CodeMeaningAction
50000Internal errorRetry after 60 seconds
50001Temporary server issueRetry up to 3 times with backoff
50002Endpoint temporarily unavailableRetry; check DataForSEO status page

Reading Error Responses

Every response has the same structure. Check status_code at two levels:

python
response = requests.post(endpoint, auth=auth, json=payload)
data = response.json()

# Level 1: overall request status
if data["status_code"] != 20000:
    print(f"Request error: {data['status_code']}{data['status_message']}")

# Level 2: per-task status
for task in data.get("tasks", []):
    if task["status_code"] not in (20000, 20100):
        print(f"Task error: {task['status_code']}{task['status_message']}")
        print(f"  Task data: {task.get('data')}")
    
    # Level 3: per-result status (some endpoints)
    for result in task.get("result", []):
        if isinstance(result, dict) and result.get("status_code"):
            if result["status_code"] != 20000:
                print(f"Result error: {result['status_code']}")

Common Error Patterns and Fixes

40101 — Access Denied on a Specific Endpoint

{"status_code": 40101, "status_message": "Access denied."}

Your account plan doesn't include this API section. DataForSEO separates SERP, Backlinks, Labs, and other sections into plan tiers. Check your dashboard under API Access to see which sections are active.

40201 — Missing Required Field

{"status_code": 40201, "status_message": "keyword field is required"}

Check the required fields for the endpoint. Most SERP endpoints require at minimum keyword and location_code. Backlink endpoints require target.

40202 — Invalid Value (depth)

{"status_code": 40202, "status_message": "depth value is invalid"}

The depth parameter has a maximum value (700 for organic SERP). Values must also be multiples of 10 on some endpoints. Use 10, 20, 50, 100, or 700.

40401 — Task Not Ready

This is not an error — it means you called task_get before the task finished. Always poll tasks_ready first:

python
# Wrong — calling task_get immediately
response = requests.get(f"...task_get/{task_id}", auth=auth)

# Right — poll tasks_ready first
while True:
    ready_data = requests.get("...tasks_ready", auth=auth).json()
    ready_ids = [r["id"] for task in ready_data["tasks"] for r in task.get("result", [])]
    if task_id in ready_ids:
        break
    time.sleep(30)

# Now safe to fetch
response = requests.get(f"...task_get/{task_id}", auth=auth)

40005 — Task Not Found (Expired)

Tasks expire after 30 days. If you try to fetch a result after 30 days, you'll get 40005. Re-run the task if you need fresh data.

429 — Rate Limit

HTTP 429 Too Many Requests

You're sending too many requests too fast. Add a delay between batches:

python
import time

for batch in batches:
    response = requests.post(endpoint, auth=auth, json=batch)
    time.sleep(1)  # 1 second between batches

Check your current rate limits:

python
response = requests.get(
    "https://api.dataforseo.com/v3/appendix/user/data",
    auth=auth
)
print(response.json())

Error Handling Template

Use this pattern in all production scripts:

python
import time
import logging

def safe_post(auth, endpoint, payload, max_retries=3):
    """POST with retry logic for transient errors."""
    
    retryable_status = {50000, 50001, 50002}
    
    for attempt in range(max_retries):
        try:
            response = requests.post(
                f"https://api.dataforseo.com/v3/{endpoint}",
                auth=auth,
                json=payload,
                timeout=30
            )
            
            # Handle HTTP errors
            if response.status_code == 429:
                wait = 60 * (attempt + 1)
                logging.warning(f"Rate limited. Waiting {wait}s...")
                time.sleep(wait)
                continue
            
            if response.status_code >= 500:
                wait = 30 * (attempt + 1)
                logging.warning(f"Server error {response.status_code}. Retry in {wait}s...")
                time.sleep(wait)
                continue
            
            data = response.json()
            
            # Handle DataForSEO-level errors
            if data["status_code"] in retryable_status:
                wait = 30 * (attempt + 1)
                logging.warning(f"DataForSEO error {data['status_code']}. Retry in {wait}s...")
                time.sleep(wait)
                continue
            
            return data
        
        except requests.exceptions.Timeout:
            logging.warning(f"Request timeout on attempt {attempt + 1}")
            time.sleep(10)
    
    raise Exception(f"Failed after {max_retries} attempts")

Internal SOP reference — not affiliated with DataForSEO.