šŸ” HTTP Response Codes & Troubleshooting

Understanding Status Codes and API Debugging

šŸ“Š 2.4 Common HTTP Response Codes Associated with REST APIs

What are HTTP Response Codes?

HTTP response codes (also called status codes) are three-digit numbers returned by a server in response to a client's request. They indicate whether the request was successful, failed, or requires additional action.

šŸ“Œ Response Code Structure:
HTTP response codes are grouped into five categories based on their first digit:
• 1xx - Informational responses
• 2xx - Success responses
• 3xx - Redirection messages
• 4xx - Client errors
• 5xx - Server errors

Status Code Categories Overview

graph TD A[HTTP Response Codes] --> B[1xx Informational] A --> C[2xx Success] A --> D[3xx Redirection] A --> E[4xx Client Error] A --> F[5xx Server Error] B --> B1["100 Continue
Request received, continue"] C --> C1["200 OK
āœ… Request successful"] C --> C2["201 Created
āœ… Resource created"] C --> C3["204 No Content
āœ… Success, no response body"] D --> D1["301 Moved Permanently
ā†Ŗļø Resource moved"] D --> D2["302 Found
ā†Ŗļø Temporary redirect"] E --> E1["400 Bad Request
āŒ Invalid syntax"] E --> E2["401 Unauthorized
āŒ Authentication required"] E --> E3["403 Forbidden
āŒ No permission"] E --> E4["404 Not Found
āŒ Resource doesn't exist"] F --> F1["500 Internal Server Error
šŸ’„ Server failure"] F --> F2["503 Service Unavailable
šŸ’„ Server overloaded"] style A fill:#667eea,stroke:#764ba2,stroke-width:3px,color:#fff style B fill:#64b5f6,stroke:#1976d2,stroke-width:2px,color:#fff style C fill:#66bb6a,stroke:#2e7d32,stroke-width:2px,color:#fff style D fill:#ffa726,stroke:#e65100,stroke-width:2px,color:#fff style E fill:#ef5350,stroke:#c62828,stroke-width:2px,color:#fff style F fill:#ab47bc,stroke:#6a1b9a,stroke-width:2px,color:#fff

1xx - Informational Responses

These codes indicate that the request was received and the process is continuing.

Code Message Description Common Use Case
100 Continue Server has received request headers; client should proceed to send body Large file uploads where server checks headers first
101 Switching Protocols Server is switching protocols as requested by client Upgrading HTTP to WebSocket connection
šŸ’” Note: 1xx status codes are rarely seen in REST APIs. They are typically handled automatically by the underlying HTTP protocol and are more common in streaming or WebSocket connections.

2xx - Success Responses

These codes indicate that the request was successfully received, understood, and accepted.

Code Message Description Common Use Case
200 OK Request succeeded; response contains requested data GET request successfully retrieves data
PUT/PATCH successfully updates resource
201 Created Request succeeded and new resource was created POST request creates a new user, device, or record
202 Accepted Request accepted for processing, but not completed Asynchronous operations (e.g., batch processing, job queue)
204 No Content Request succeeded but no content to return DELETE request successfully removes a resource
PUT update with no response body needed
āœ… Best Practice: Use the appropriate 2xx code:
  • 200 OK - Default success for GET, PUT, PATCH
  • 201 Created - Always use for POST when creating resources
  • 204 No Content - Use for DELETE or when no response body is needed

3xx - Redirection Messages

These codes indicate that the client must take additional action to complete the request.

Code Message Description Common Use Case
301 Moved Permanently Resource has been permanently moved to new URL API versioning (v1 → v2), domain changes
302 Found (Temporary Redirect) Resource temporarily at different URL Temporary maintenance, A/B testing
304 Not Modified Cached version is still valid; no new data to send Conditional GET requests with If-Modified-Since header
307 Temporary Redirect Like 302 but guarantees HTTP method won't change Temporary redirects where method must stay POST/PUT/DELETE
308 Permanent Redirect Like 301 but guarantees HTTP method won't change Permanent redirects where method must stay POST/PUT/DELETE
šŸ“Œ Redirect Behavior:
• 301/302: May change POST to GET
• 307/308: Preserve original HTTP method
• Clients should follow redirect automatically or provide new location to user

4xx - Client Error Responses

These codes indicate that the request contains bad syntax or cannot be fulfilled due to client error.

Code Message Description Common Use Case
400 Bad Request Server cannot process request due to invalid syntax Malformed JSON, missing required fields, invalid data types
401 Unauthorized Authentication required or failed Missing/invalid token, expired credentials, wrong password
403 Forbidden Client authenticated but doesn't have permission Insufficient privileges, accessing admin-only resource
404 Not Found Requested resource doesn't exist Wrong URL/endpoint, resource deleted, invalid ID
405 Method Not Allowed HTTP method not supported for this endpoint Using POST on read-only endpoint, DELETE on protected resource
408 Request Timeout Server timed out waiting for request Slow client connection, large file upload interrupted
409 Conflict Request conflicts with current state Duplicate resource creation, concurrent update conflicts
415 Unsupported Media Type Request payload format not supported Sending XML when API expects JSON, wrong Content-Type header
422 Unprocessable Entity Request well-formed but semantically invalid Validation errors (email format wrong, age negative, etc.)
429 Too Many Requests Rate limit exceeded API quota exceeded, too many requests in time window
āš ļø Common Confusion: 401 vs 403
• 401 Unauthorized: "Who are you?" - Authentication problem (invalid/missing credentials)
• 403 Forbidden: "I know who you are, but you can't do that" - Authorization problem (insufficient permissions)

5xx - Server Error Responses

These codes indicate that the server failed to fulfill a valid request.

Code Message Description Common Use Case
500 Internal Server Error Generic server error; something went wrong Unhandled exceptions, database errors, code bugs
501 Not Implemented Server doesn't support functionality required Feature not yet implemented, unsupported HTTP method
502 Bad Gateway Server acting as gateway received invalid response Reverse proxy can't reach backend, upstream server down
503 Service Unavailable Server temporarily unable to handle request Maintenance mode, server overloaded, temporary outage
504 Gateway Timeout Server acting as gateway didn't get timely response Upstream server too slow, database query timeout
šŸ”„ Important: 5xx errors indicate server-side problems. As a client/developer, you typically cannot fix these directly - contact the API provider or wait for service restoration.

Python Example: Checking Status Codes

#!/usr/bin/env python3
"""
HTTP Status Code Handling Example
Demonstrates how to handle different response codes in Python
"""

import requests


def make_api_request_with_error_handling(url, method="GET", **kwargs):
    """
    Make API request with comprehensive status code handling
    
    Args:
        url (str): API endpoint URL
        method (str): HTTP method (GET, POST, PUT, DELETE, etc.)
        **kwargs: Additional arguments for requests (headers, data, etc.)
    """
    try:
        # Make the request
        response = requests.request(method, url, **kwargs)
        status_code = response.status_code
        
        print(f"šŸ“” Request: {method} {url}")
        print(f"šŸ“Š Status Code: {status_code}")
        print(f"šŸ“ Status Message: {response.reason}")
        print("-" * 60)
        
        # Handle different status code ranges
        if 200 <= status_code < 300:
            # 2xx - Success
            print("āœ… SUCCESS")
            if status_code == 200:
                print("Request successful, data returned")
                return response.json() if response.content else None
            elif status_code == 201:
                print("Resource created successfully")
                print(f"Location: {response.headers.get('Location', 'N/A')}")
                return response.json() if response.content else None
            elif status_code == 204:
                print("Request successful, no content returned")
                return None
            else:
                print(f"Success with status {status_code}")
                return response.json() if response.content else None
        
        elif 300 <= status_code < 400:
            # 3xx - Redirection
            print("ā†Ŗļø REDIRECTION")
            new_location = response.headers.get('Location', 'Not specified')
            print(f"Redirect to: {new_location}")
            if status_code in [301, 308]:
                print("Permanent redirect - update bookmarks/links")
            elif status_code in [302, 307]:
                print("Temporary redirect - original URL still valid")
            return None
        
        elif 400 <= status_code < 500:
            # 4xx - Client Error
            print("āŒ CLIENT ERROR")
            if status_code == 400:
                print("Bad Request - check request syntax and data")
            elif status_code == 401:
                print("Unauthorized - authentication required/failed")
                print("Action: Check credentials, token, or API key")
            elif status_code == 403:
                print("Forbidden - insufficient permissions")
                print("Action: Verify account has required privileges")
            elif status_code == 404:
                print("Not Found - resource doesn't exist")
                print("Action: Verify URL/endpoint and resource ID")
            elif status_code == 405:
                print("Method Not Allowed - HTTP method not supported")
                print(f"Allowed methods: {response.headers.get('Allow', 'N/A')}")
            elif status_code == 409:
                print("Conflict - request conflicts with current state")
            elif status_code == 415:
                print("Unsupported Media Type - check Content-Type header")
            elif status_code == 422:
                print("Unprocessable Entity - validation failed")
            elif status_code == 429:
                print("Too Many Requests - rate limit exceeded")
                retry_after = response.headers.get('Retry-After', 'N/A')
                print(f"Retry after: {retry_after} seconds")
            
            # Try to get error details from response
            try:
                error_data = response.json()
                print(f"Error details: {error_data}")
            except:
                print(f"Error message: {response.text}")
            
            return None
        
        elif 500 <= status_code < 600:
            # 5xx - Server Error
            print("šŸ’„ SERVER ERROR")
            if status_code == 500:
                print("Internal Server Error - server encountered an error")
            elif status_code == 502:
                print("Bad Gateway - upstream server issue")
            elif status_code == 503:
                print("Service Unavailable - server temporarily down")
                retry_after = response.headers.get('Retry-After', 'N/A')
                print(f"Retry after: {retry_after}")
            elif status_code == 504:
                print("Gateway Timeout - upstream server didn't respond")
            
            print("Action: Contact API provider or try again later")
            return None
        
    except requests.exceptions.ConnectionError:
        print("āŒ Connection Error: Cannot reach the server")
        print("Action: Check internet connection and server availability")
    except requests.exceptions.Timeout:
        print("āŒ Timeout Error: Request took too long")
        print("Action: Try again or increase timeout")
    except requests.exceptions.RequestException as e:
        print(f"āŒ Request Error: {e}")
    
    return None


# =============================================================================
# USAGE EXAMPLES
# =============================================================================

if __name__ == "__main__":
    # Example 1: Successful GET request (200 OK)
    print("\n" + "="*60)
    print("Example 1: GET Request")
    print("="*60)
    make_api_request_with_error_handling(
        "https://jsonplaceholder.typicode.com/posts/1"
    )
    
    # Example 2: Successful POST request (201 Created)
    print("\n" + "="*60)
    print("Example 2: POST Request")
    print("="*60)
    make_api_request_with_error_handling(
        "https://jsonplaceholder.typicode.com/posts",
        method="POST",
        headers={"Content-Type": "application/json"},
        json={"title": "Test", "body": "Test body", "userId": 1}
    )
    
    # Example 3: 404 Not Found
    print("\n" + "="*60)
    print("Example 3: 404 Not Found")
    print("="*60)
    make_api_request_with_error_handling(
        "https://jsonplaceholder.typicode.com/posts/99999"
    )
    
    # Example 4: 401 Unauthorized (simulated)
    print("\n" + "="*60)
    print("Example 4: 401 Unauthorized")
    print("="*60)
    # This is a hypothetical example - actual API might differ
    make_api_request_with_error_handling(
        "https://api.github.com/user",
        headers={"Authorization": "Bearer invalid_token"}
    )

Quick Reference: Most Common Status Codes

šŸŽÆ Top 10 Status Codes You'll Encounter:
  1. 200 OK - Standard success response
  2. 201 Created - Resource created successfully
  3. 204 No Content - Success with no body
  4. 400 Bad Request - Invalid request syntax
  5. 401 Unauthorized - Authentication needed
  6. 403 Forbidden - No permission
  7. 404 Not Found - Resource doesn't exist
  8. 429 Too Many Requests - Rate limited
  9. 500 Internal Server Error - Server problem
  10. 503 Service Unavailable - Temporarily down

šŸ”§ 2.5 Troubleshoot a Problem Given HTTP Response Code, Request, and API Documentation

The Troubleshooting Process

Troubleshooting API issues requires a systematic approach. When you encounter an error, you need to analyze three key components: the HTTP response code, the request you sent, and the API documentation.

graph TD A["API Request Fails"] --> B["Gather Information"] B --> C["HTTP Response Code"] B --> D["Request Details"] B --> E["API Documentation"] C --> F["Analyze Status Code"] D --> F E --> F F --> G["2xx Success"] F --> H["4xx Client Error"] F --> I["5xx Server Error"] H --> J["Check Request Components"] J --> K["URL and Endpoint"] J --> L["Headers"] J --> M["Authentication"] J --> N["Request Body"] K --> O["Compare with Documentation"] L --> O M --> O N --> O O --> P["Fix Issues"] P --> Q["Retry Request"] Q --> R["Problem Resolved"] I --> S["Check API Status"] I --> T["Wait and Retry"] I --> U["Contact Support"] style A fill:#ff6b6b,stroke:#c92a2a,stroke-width:2px,color:#fff style G fill:#51cf66,stroke:#2f9e44,stroke-width:2px,color:#fff style H fill:#ffa726,stroke:#e65100,stroke-width:2px,color:#fff style I fill:#ab47bc,stroke:#6a1b9a,stroke-width:2px,color:#fff style R fill:#51cf66,stroke:#2f9e44,stroke-width:2px,color:#fff
šŸ” Troubleshooting Workflow Explained:
  1. Gather Information: Collect the HTTP response code, your request details, and API documentation
  2. Analyze Status Code: Determine if it's a success (2xx), client error (4xx), or server error (5xx)
  3. Client Errors (4xx): Review your request components and compare with documentation
  4. Server Errors (5xx): Check API status, implement retry logic, or contact support
  5. Test and Verify: After fixing issues, retry the request and verify success

Step-by-Step Troubleshooting Guide

Step 1: Identify the Status Code Category

šŸ” What to Check: Look at the first digit of the status code to determine the error category:
  • 4xx: Problem is with YOUR request (client-side)
  • 5xx: Problem is with THE SERVER (server-side)
šŸ’” Action: • For 4xx errors: Review and fix your request
• For 5xx errors: Check API status, wait, or contact support

Step 2: Examine the Response Body

šŸ” What to Check: Most APIs return detailed error information in the response body:
  • Error message or description
  • Error code (API-specific)
  • Validation errors with field names
  • Suggestions for fixing the issue

Step 3: Verify Request Components

šŸ” Checklist:
Component What to Verify Common Issues
URL/Endpoint • Correct base URL
• Proper path
• Valid resource ID
Typos, wrong version (v1 vs v2), missing slashes
HTTP Method • Using correct method
• Method is allowed
Using POST instead of PUT, DELETE not allowed
Headers • Content-Type set
• Accept header
• Custom headers
Missing Content-Type, wrong format specified
Authentication • Token present
• Token not expired
• Correct format
Missing "Bearer" prefix, expired token, wrong header
Request Body • Valid JSON/XML
• All required fields
• Correct data types
Invalid JSON syntax, missing fields, wrong types

Step 4: Compare with API Documentation

šŸ” Documentation Review:
  • Verify endpoint path and structure
  • Check required vs optional parameters
  • Review example requests and responses
  • Check authentication requirements
  • Look for rate limits and quotas
  • Review data format specifications

Common Scenarios & Solutions

šŸ”“ Scenario 1: 401 Unauthorized

Error Message: "Authentication failed" or "Invalid credentials"

Possible Causes:
  • Missing authentication token/API key
  • Expired token
  • Invalid token format
  • Wrong authentication header name
Troubleshooting Steps:
# Step 1: Check if Authorization header exists
headers = {
    "Authorization": "Bearer YOUR_TOKEN_HERE"  # āœ… Correct
    # "Authorization": "YOUR_TOKEN_HERE"       # āŒ Missing "Bearer"
}

# Step 2: Verify token hasn't expired
import jwt
import datetime

try:
    decoded = jwt.decode(token, options={"verify_signature": False})
    exp = decoded.get('exp')
    if exp and datetime.datetime.fromtimestamp(exp) < datetime.datetime.now():
        print("āŒ Token expired!")
    else:
        print("āœ… Token is valid")
except:
    print("āŒ Invalid token format")

# Step 3: Check documentation for correct header name
# Some APIs use different header names:
# - "Authorization": "Bearer token"
# - "X-API-Key": "key"
# - "Api-Token": "token"
Solution:
  1. Obtain fresh authentication token
  2. Verify correct authorization header format
  3. Ensure "Bearer" prefix if using JWT
  4. Check token hasn't expired

šŸ”“ Scenario 2: 400 Bad Request

Error Message: "Invalid request syntax" or "Malformed JSON"

Possible Causes:
  • Invalid JSON syntax
  • Missing required fields
  • Wrong data types
  • Invalid characters in request
Troubleshooting Steps:
# Step 1: Validate JSON syntax
import json

request_body = '''
{
    "name": "John",
    "age": 30,      # āŒ Comments not allowed in JSON
    "email": "john@example.com"
}
'''

try:
    data = json.loads(request_body)
    print("āœ… Valid JSON")
except json.JSONDecodeError as e:
    print(f"āŒ Invalid JSON: {e}")

# Step 2: Verify all required fields are present
required_fields = ["name", "email", "age"]
data = {"name": "John", "email": "john@example.com"}  # Missing "age"

missing = [field for field in required_fields if field not in data]
if missing:
    print(f"āŒ Missing required fields: {missing}")

# Step 3: Check data types match documentation
data = {
    "name": "John",        # āœ… String
    "age": "30",           # āŒ Should be int, not string
    "active": "true"       # āŒ Should be boolean, not string
}

# Correct version:
data = {
    "name": "John",
    "age": 30,
    "active": True
}
Solution:
  1. Use JSON validator to check syntax
  2. Add all required fields from documentation
  3. Match data types exactly as specified
  4. Remove comments and trailing commas

šŸ”“ Scenario 3: 404 Not Found

Error Message: "Resource not found" or "Endpoint does not exist"

Possible Causes:
  • Incorrect URL/endpoint path
  • Wrong API version
  • Invalid resource ID
  • Resource was deleted
  • Typo in URL
Troubleshooting Steps:
# Step 1: Verify base URL and endpoint
# Documentation says:
base_url = "https://api.example.com/v2"
endpoint = "/users/123"

# Common mistakes:
wrong_url_1 = "https://api.example.com/v1/users/123"  # āŒ Wrong version
wrong_url_2 = "https://api.example.com/v2/user/123"   # āŒ "user" not "users"
wrong_url_3 = "https://api.example.com/v2/users/123/" # āŒ Trailing slash
correct_url = "https://api.example.com/v2/users/123"  # āœ… Correct

# Step 2: Check if resource ID exists
# Try listing all resources first
response = requests.get(f"{base_url}/users")
users = response.json()
print([user['id'] for user in users])  # See valid IDs

# Step 3: Verify URL construction
user_id = 123
url = f"{base_url}/users/{user_id}"
print(f"Requesting: {url}")

# Check for spaces or special characters
if " " in url:
    print("āŒ URL contains spaces!")
Solution:
  1. Double-check URL against documentation
  2. Verify API version is correct
  3. Confirm resource ID is valid
  4. Check for typos and trailing slashes
  5. Test with known working resource ID

šŸ”“ Scenario 4: 403 Forbidden

Error Message: "Access denied" or "Insufficient permissions"

Possible Causes:
  • Insufficient account permissions
  • Resource access restricted
  • IP address not whitelisted
  • Subscription/plan limitation
Troubleshooting Steps:
# Step 1: Verify authentication is working (not 401)
# 403 means you're authenticated but not authorized

# Step 2: Check user permissions/roles
# Review your account settings:
# - Do you have admin/write permissions?
# - Is your subscription active?
# - Are you trying to access someone else's resource?

# Step 3: Check if endpoint requires special permission
# Documentation might specify:
# "DELETE /users/:id - Requires 'admin' role"
# "GET /analytics - Requires 'premium' subscription"

# Step 4: Verify resource ownership
# You might only be allowed to access YOUR resources
user_id = "current_user_123"
other_user_id = "other_user_456"

# āœ… Allowed: Access your own data
url = f"{base_url}/users/{user_id}/profile"

# āŒ Forbidden: Access someone else's data
url = f"{base_url}/users/{other_user_id}/profile"
Solution:
  1. Verify account has required permissions/role
  2. Check subscription plan supports this feature
  3. Ensure accessing only authorized resources
  4. Contact API provider to request access

šŸ”“ Scenario 5: 429 Too Many Requests

Error Message: "Rate limit exceeded" or "Too many requests"

Possible Causes:
  • Exceeded requests per second limit
  • Exceeded daily/hourly quota
  • Too many concurrent requests
Troubleshooting Steps:
# Step 1: Check rate limit headers
response = requests.get(url)
print(f"Rate Limit: {response.headers.get('X-RateLimit-Limit')}")
print(f"Remaining: {response.headers.get('X-RateLimit-Remaining')}")
print(f"Reset: {response.headers.get('X-RateLimit-Reset')}")
print(f"Retry After: {response.headers.get('Retry-After')} seconds")

# Step 2: Implement exponential backoff
import time

def make_request_with_retry(url, max_retries=3):
    for attempt in range(max_retries):
        response = requests.get(url)
        
        if response.status_code == 429:
            retry_after = int(response.headers.get('Retry-After', 60))
            print(f"Rate limited. Waiting {retry_after} seconds...")
            time.sleep(retry_after)
            continue
        
        return response
    
    raise Exception("Max retries exceeded")

# Step 3: Add delays between requests
import time

urls = ["url1", "url2", "url3"]
for url in urls:
    response = requests.get(url)
    time.sleep(1)  # Wait 1 second between requests

# Step 4: Use batch endpoints if available
# Instead of making 100 individual requests:
# for user_id in user_ids:
#     requests.get(f"/users/{user_id}")

# Use batch endpoint if available:
# requests.post("/users/batch", json={"ids": user_ids})
Solution:
  1. Implement rate limiting in your code
  2. Add delays between requests
  3. Use batch endpoints when available
  4. Cache responses to reduce requests
  5. Consider upgrading to higher tier

šŸ”“ Scenario 6: 500 Internal Server Error

Error Message: "Internal server error" or "Something went wrong"

Possible Causes:
  • Bug in API server code
  • Database connection error
  • Unexpected data causing crash
  • Server resource exhaustion
Troubleshooting Steps:
# Step 1: Verify it's not your request
# Try a simple, known-working request
response = requests.get(f"{base_url}/health")  # Health check endpoint
if response.status_code == 500:
    print("āŒ Server is experiencing issues")
else:
    print("āœ… Server is healthy, issue is with specific request")

# Step 2: Check if your data triggers the error
# Try with minimal/sample data first
minimal_data = {"name": "Test"}  # Minimal valid request
response = requests.post(url, json=minimal_data)

if response.status_code == 200:
    print("āœ… Minimal data works")
    # Your full request might have problematic data
else:
    print("āŒ Even minimal request fails - server issue")

# Step 3: Implement retry logic with exponential backoff
import time

def make_request_with_retry(url, max_retries=3):
    for attempt in range(max_retries):
        try:
            response = requests.get(url, timeout=30)
            
            if response.status_code == 500:
                wait_time = 2 ** attempt  # Exponential backoff: 1, 2, 4 seconds
                print(f"Server error. Retry {attempt + 1}/{max_retries} in {wait_time}s")
                time.sleep(wait_time)
                continue
            
            return response
            
        except requests.exceptions.Timeout:
            print(f"Timeout on attempt {attempt + 1}")
            continue
    
    raise Exception("Server error persists after retries")

# Step 4: Check API status page
print("Check: https://status.api-provider.com")
Solution:
  1. Check API status/health page
  2. Wait a few minutes and retry
  3. Implement retry logic with backoff
  4. Report issue to API provider with request details
  5. Use monitoring to track frequency

Debugging Tools and Techniques

šŸ› ļø Essential Debugging Tools:
  1. Browser Developer Tools (Network Tab)
    • View all request/response details
    • See headers, body, timing
    • Copy as cURL command
  2. Postman / Insomnia
    • Test API endpoints interactively
    • Save and organize requests
    • View formatted responses
  3. cURL
    • Command-line API testing
    • Easy to share and reproduce issues
  4. Python Logging
    • Log all request/response details
    • Track down intermittent issues
  5. API Monitoring Tools
    • Uptime monitors
    • Response time tracking
    • Error rate alerts

Complete Troubleshooting Example

#!/usr/bin/env python3
"""
Complete API Troubleshooting Example
Demonstrates how to debug and fix common API issues
"""

import requests
import json
import logging
from datetime import datetime

# Configure logging to see all request details
logging.basicConfig(level=logging.DEBUG)


class APITroubleshooter:
    """Helper class for troubleshooting API requests"""
    
    def __init__(self, base_url):
        self.base_url = base_url
        self.session = requests.Session()
    
    def diagnose_request(self, method, endpoint, **kwargs):
        """
        Make request and provide detailed diagnostic information
        """
        url = f"{self.base_url}{endpoint}"
        
        print("="*70)
        print(f"šŸ” DIAGNOSING REQUEST")
        print("="*70)
        
        # Display request details
        print(f"\nšŸ“¤ REQUEST DETAILS:")
        print(f"   Method:   {method}")
        print(f"   URL:      {url}")
        print(f"   Headers:  {json.dumps(kwargs.get('headers', {}), indent=13)}")
        
        if 'json' in kwargs:
            print(f"   Body:     {json.dumps(kwargs['json'], indent=13)}")
        
        try:
            # Make the request
            response = self.session.request(method, url, **kwargs)
            
            # Display response details
            print(f"\nšŸ“„ RESPONSE DETAILS:")
            print(f"   Status:   {response.status_code} {response.reason}")
            print(f"   Headers:  {json.dumps(dict(response.headers), indent=13)}")
            
            # Try to parse response body
            try:
                body = response.json()
                print(f"   Body:     {json.dumps(body, indent=13)}")
            except:
                print(f"   Body:     {response.text[:500]}")
            
            # Analyze the response
            print(f"\nšŸ” ANALYSIS:")
            self._analyze_response(response, kwargs)
            
            return response
            
        except requests.exceptions.RequestException as e:
            print(f"\nāŒ REQUEST FAILED: {e}")
            return None
    
    def _analyze_response(self, response, request_kwargs):
        """Analyze response and provide troubleshooting suggestions"""
        status = response.status_code
        
        if 200 <= status < 300:
            print("   āœ… SUCCESS - Request completed successfully")
            
        elif status == 400:
            print("   āŒ BAD REQUEST - Check request syntax and data")
            print("\n   Checklist:")
            print("   [ ] Is the JSON valid?")
            print("   [ ] Are all required fields present?")
            print("   [ ] Are data types correct?")
            print("   [ ] Is Content-Type header set?")
            
        elif status == 401:
            print("   āŒ UNAUTHORIZED - Authentication failed")
            print("\n   Checklist:")
            print("   [ ] Is Authorization header present?")
            print("   [ ] Is token format correct (Bearer )?")
            print("   [ ] Has the token expired?")
            print("   [ ] Is the token valid for this API?")
            
            headers = request_kwargs.get('headers', {})
            if 'Authorization' not in headers:
                print("\n   āš ļø  WARNING: No Authorization header found!")
            else:
                auth = headers['Authorization']
                if not auth.startswith('Bearer '):
                    print(f"\n   āš ļø  WARNING: Token might be missing 'Bearer' prefix")
                    
        elif status == 403:
            print("   āŒ FORBIDDEN - Insufficient permissions")
            print("\n   Checklist:")
            print("   [ ] Does your account have required permissions?")
            print("   [ ] Are you accessing your own resources?")
            print("   [ ] Does your plan/subscription support this?")
            print("   [ ] Is your IP address whitelisted?")
            
        elif status == 404:
            print("   āŒ NOT FOUND - Resource or endpoint doesn't exist")
            print("\n   Checklist:")
            print("   [ ] Is the URL correct?")
            print("   [ ] Is the API version correct?")
            print("   [ ] Does the resource ID exist?")
            print("   [ ] Are there any typos?")
            print("   [ ] Is there a trailing slash issue?")
            
        elif status == 422:
            print("   āŒ UNPROCESSABLE ENTITY - Validation failed")
            print("\n   Check response body for validation error details")
            
        elif status == 429:
            print("   āŒ TOO MANY REQUESTS - Rate limit exceeded")
            retry_after = response.headers.get('Retry-After')
            if retry_after:
                print(f"\n   ā±ļø  Retry after: {retry_after} seconds")
            print("\n   Suggestions:")
            print("   • Add delays between requests")
            print("   • Implement exponential backoff")
            print("   • Use batch endpoints if available")
            print("   • Consider caching responses")
            
        elif 500 <= status < 600:
            print("   āŒ SERVER ERROR - Problem with API server")
            print("\n   Actions:")
            print("   • Check API status page")
            print("   • Wait and retry with exponential backoff")
            print("   • Contact API support if persists")
            print("   • Verify with minimal test request")


# =============================================================================
# DEMONSTRATION
# =============================================================================

if __name__ == "__main__":
    # Initialize troubleshooter
    troubleshooter = APITroubleshooter("https://jsonplaceholder.typicode.com")
    
    # Example 1: Successful request
    print("\n" + "🟢 EXAMPLE 1: Successful GET Request")
    troubleshooter.diagnose_request(
        "GET",
        "/posts/1"
    )
    
    input("\nPress Enter to continue to next example...")
    
    # Example 2: 404 Not Found
    print("\n" + "šŸ”“ EXAMPLE 2: 404 Not Found")
    troubleshooter.diagnose_request(
        "GET",
        "/posts/99999"  # Non-existent resource
    )
    
    input("\nPress Enter to continue to next example...")
    
    # Example 3: Successful POST
    print("\n" + "🟢 EXAMPLE 3: Successful POST Request")
    troubleshooter.diagnose_request(
        "POST",
        "/posts",
        headers={"Content-Type": "application/json"},
        json={
            "title": "Test Post",
            "body": "This is a test",
            "userId": 1
        }
    )
    
    input("\nPress Enter to continue to next example...")
    
    # Example 4: Bad Request (simulated with GitHub API)
    print("\n" + "šŸ”“ EXAMPLE 4: 401 Unauthorized")
    github_ts = APITroubleshooter("https://api.github.com")
    github_ts.diagnose_request(
        "GET",
        "/user",
        headers={"Authorization": "Bearer invalid_token_12345"}
    )

Best Practices for API Troubleshooting

āœ… Troubleshooting Checklist:
  1. Start with the status code - it tells you WHERE the problem is
  2. Read the error response body - it often tells you WHAT is wrong
  3. Compare your request with documentation examples
  4. Test with a minimal, simplified request first
  5. Use debugging tools to inspect raw HTTP traffic
  6. Check authentication and authorization separately
  7. Verify data types and JSON syntax
  8. Look for rate limiting and implement backoff
  9. Check API status page for outages
  10. Keep detailed logs for intermittent issues
šŸ’” Pro Tips:
  • Use Postman first: Get the request working in Postman before coding
  • Copy as cURL: Browser DevTools can copy requests as cURL commands
  • Enable verbose logging: See exactly what's being sent and received
  • Test authentication separately: Verify auth works before testing complex requests
  • Keep a "working request": Use as reference when new requests fail
  • Check for updates: API documentation and behavior can change

šŸ Interactive Python Interpreter

šŸ’” How to use:
  • Write Python code in the editor below
  • Click "ā–¶ Run Code" to execute
  • Output appears in the console below
  • Use sample codes for quick testing
  • Experiment with status code handling and troubleshooting techniques
šŸ“ Python Code Editor
⚔ Console Output
Ready to execute Python code...
āš ļø Note: This is a client-side Python interpreter using Skulpt. It supports basic Python syntax but has limitations:
  • No real network requests (use mock data)
  • Limited library support
  • Perfect for learning and testing logic