Catching Anomalies via requests.exceptions.ConnectionError
๐ท๏ธ APIs and HTTP Requests / Timeouts and Error Handling
๐ง Context Introduction
When your Python script reaches out to an external API or web service, things don't always go smoothly. Network issues, server downtime, or firewall blocks can cause your connection to fail. The requests.exceptions.ConnectionError is a built-in exception in the requests library that catches these network-level failures. Understanding how to catch and handle this error helps you build resilient scripts that don't crash unexpectedly when the network misbehaves.
โ๏ธ What is a ConnectionError?
A ConnectionError occurs when your Python script cannot establish a TCP connection to the target server. This is different from a timeout (where the connection starts but takes too long) or an HTTP error (where the server responds with a 4xx or 5xx status code).
Common scenarios that trigger a ConnectionError: - The server is offline or unreachable - A firewall is blocking the connection - The domain name does not resolve to an IP address - The port is closed on the target server - Network cables are unplugged or Wi-Fi is disconnected
๐ ๏ธ How to Catch a ConnectionError
To catch this exception, you first import the requests library and then wrap your HTTP call inside a try-except block. The exception class is accessed as requests.exceptions.ConnectionError.
Basic structure: - Import the requests library at the top of your script - Place your requests.get() or requests.post() call inside a try block - Use except requests.exceptions.ConnectionError to catch the failure - Inside the except block, print a meaningful message or log the error
Example scenario: - You try to fetch data from https://api.example.com/status - If the server is down, the script prints "Unable to connect to the API server. Please check network connectivity." instead of crashing
๐ Comparison: ConnectionError vs Other Exceptions
| Exception Type | When It Occurs | Example Cause |
|---|---|---|
| ConnectionError | Cannot establish TCP connection | Server offline, firewall block |
| Timeout | Connection established but no response within time limit | Slow server, network congestion |
| HTTPError | Server responds with error status code (4xx, 5xx) | Invalid endpoint, authentication failure |
| RequestException | Parent class for all requests exceptions | Catch-all for any request failure |
๐ต๏ธ Real-World Anomaly Detection Patterns
When monitoring infrastructure, catching ConnectionError helps you detect anomalies like:
- Service outages: A critical API suddenly becomes unreachable
- Network partitions: Internal services cannot communicate due to firewall changes
- DNS failures: Domain resolution stops working after DNS configuration changes
- Port changes: A service moves to a different port without updating your configuration
Detection workflow: - Wrap each external API call in a try-except block for ConnectionError - Log the error with a timestamp and the target URL - Increment a failure counter for that endpoint - Trigger an alert if failures exceed a threshold (e.g., 3 consecutive failures)
๐งช Best Practices for Handling ConnectionError
- Always catch ConnectionError separately from other exceptions to handle network issues differently than application errors
- Implement retry logic with exponential backoff โ wait 1 second, then 2 seconds, then 4 seconds before retrying
- Log the full error details including the target URL and timestamp for debugging
- Set a reasonable timeout using the timeout parameter in your request to avoid hanging indefinitely
- Check network prerequisites before making the request, such as verifying DNS resolution with socket.gethostbyname()
Example retry strategy: - Attempt 1: Immediate retry after 1 second - Attempt 2: Retry after 2 seconds - Attempt 3: Retry after 4 seconds - After 3 failures: Log the error and exit gracefully
๐จ Common Pitfalls to Avoid
- Catching ConnectionError too broadly โ do not catch all exceptions with a bare except: clause
- Ignoring the error silently โ always log or print the error for visibility
- Not setting a timeout โ without a timeout, your script may hang forever waiting for a connection
- Retrying immediately without delay โ this can overwhelm a struggling server or network
- Assuming all connection failures are the same โ distinguish between DNS failures, refused connections, and network unreachable errors using the exception's args or response attribute
โ Summary
Catching requests.exceptions.ConnectionError is a fundamental skill for building robust Python scripts that interact with external services. By handling network failures gracefully, you prevent your scripts from crashing and gain visibility into infrastructure anomalies. Always combine this with proper logging, retry logic, and timeout settings to create production-ready code that can withstand real-world network conditions.
This exception is raised when a network connection cannot be established to the target server, allowing engineers to handle network failures gracefully.
๐งช Example 1: Basic ConnectionError catch with a fake URL
This example shows how to catch a connection error when the server does not exist.
import requests
try:
response = requests.get("https://this-domain-does-not-exist-12345.com")
except requests.exceptions.ConnectionError:
print("Connection failed โ server not reachable")
๐ค Output: Connection failed โ server not reachable
๐งช Example 2: Catching ConnectionError with a timeout
This example demonstrates that a timeout is a different exception, not a ConnectionError.
import requests
try:
response = requests.get("https://httpbin.org/delay/10", timeout=2)
except requests.exceptions.ConnectionError:
print("ConnectionError caught")
except requests.exceptions.Timeout:
print("Timeout caught โ this is NOT a ConnectionError")
๐ค Output: Timeout caught โ this is NOT a ConnectionError
๐งช Example 3: Distinguishing between ConnectionError and other exceptions
This example shows how to handle ConnectionError separately from other request failures.
import requests
url = "https://httpbin.org/status/500"
try:
response = requests.get(url)
response.raise_for_status()
except requests.exceptions.ConnectionError:
print("Could not connect to the server")
except requests.exceptions.HTTPError:
print("Server responded with an error status code")
๐ค Output: Server responded with an error status code
๐งช Example 4: Retrying after a ConnectionError
This example shows a simple retry pattern when a connection fails temporarily.
import requests
import time
url = "https://httpbin.org/status/200"
max_retries = 3
for attempt in range(max_retries):
try:
response = requests.get(url, timeout=5)
print("Success on attempt", attempt + 1)
break
except requests.exceptions.ConnectionError:
print("Attempt", attempt + 1, "failed โ retrying in 2 seconds")
time.sleep(2)
else:
print("All retries exhausted โ connection still failing")
๐ค Output: Success on attempt 1
๐งช Example 5: Logging the full error details for debugging
This example shows how to capture and display the underlying error message from a ConnectionError.
import requests
try:
response = requests.get("https://localhost:9999", timeout=3)
except requests.exceptions.ConnectionError as error:
print("ConnectionError details:")
print(" Type:", type(error).__name__)
print(" Message:", str(error))
๐ค Output: ConnectionError details: / Type: ConnectionError / Message: HTTPConnectionPool(host='localhost', port=9999): Max retries exceeded with url: / (Caused by NewConnectionError('
Comparison Table
| Scenario | Exception Type | Typical Cause |
|---|---|---|
| Server does not exist | ConnectionError | DNS resolution failure or unreachable host |
| Server refuses connection | ConnectionError | Port closed or service not running |
| Request takes too long | Timeout | Server slow or network congestion |
| Server returns error status | HTTPError | 4xx or 5xx response code |
| Invalid URL format | InvalidURL | Malformed URL string |
๐ง Context Introduction
When your Python script reaches out to an external API or web service, things don't always go smoothly. Network issues, server downtime, or firewall blocks can cause your connection to fail. The requests.exceptions.ConnectionError is a built-in exception in the requests library that catches these network-level failures. Understanding how to catch and handle this error helps you build resilient scripts that don't crash unexpectedly when the network misbehaves.
โ๏ธ What is a ConnectionError?
A ConnectionError occurs when your Python script cannot establish a TCP connection to the target server. This is different from a timeout (where the connection starts but takes too long) or an HTTP error (where the server responds with a 4xx or 5xx status code).
Common scenarios that trigger a ConnectionError: - The server is offline or unreachable - A firewall is blocking the connection - The domain name does not resolve to an IP address - The port is closed on the target server - Network cables are unplugged or Wi-Fi is disconnected
๐ ๏ธ How to Catch a ConnectionError
To catch this exception, you first import the requests library and then wrap your HTTP call inside a try-except block. The exception class is accessed as requests.exceptions.ConnectionError.
Basic structure: - Import the requests library at the top of your script - Place your requests.get() or requests.post() call inside a try block - Use except requests.exceptions.ConnectionError to catch the failure - Inside the except block, print a meaningful message or log the error
Example scenario: - You try to fetch data from https://api.example.com/status - If the server is down, the script prints "Unable to connect to the API server. Please check network connectivity." instead of crashing
๐ Comparison: ConnectionError vs Other Exceptions
| Exception Type | When It Occurs | Example Cause |
|---|---|---|
| ConnectionError | Cannot establish TCP connection | Server offline, firewall block |
| Timeout | Connection established but no response within time limit | Slow server, network congestion |
| HTTPError | Server responds with error status code (4xx, 5xx) | Invalid endpoint, authentication failure |
| RequestException | Parent class for all requests exceptions | Catch-all for any request failure |
๐ต๏ธ Real-World Anomaly Detection Patterns
When monitoring infrastructure, catching ConnectionError helps you detect anomalies like:
- Service outages: A critical API suddenly becomes unreachable
- Network partitions: Internal services cannot communicate due to firewall changes
- DNS failures: Domain resolution stops working after DNS configuration changes
- Port changes: A service moves to a different port without updating your configuration
Detection workflow: - Wrap each external API call in a try-except block for ConnectionError - Log the error with a timestamp and the target URL - Increment a failure counter for that endpoint - Trigger an alert if failures exceed a threshold (e.g., 3 consecutive failures)
๐งช Best Practices for Handling ConnectionError
- Always catch ConnectionError separately from other exceptions to handle network issues differently than application errors
- Implement retry logic with exponential backoff โ wait 1 second, then 2 seconds, then 4 seconds before retrying
- Log the full error details including the target URL and timestamp for debugging
- Set a reasonable timeout using the timeout parameter in your request to avoid hanging indefinitely
- Check network prerequisites before making the request, such as verifying DNS resolution with socket.gethostbyname()
Example retry strategy: - Attempt 1: Immediate retry after 1 second - Attempt 2: Retry after 2 seconds - Attempt 3: Retry after 4 seconds - After 3 failures: Log the error and exit gracefully
๐จ Common Pitfalls to Avoid
- Catching ConnectionError too broadly โ do not catch all exceptions with a bare except: clause
- Ignoring the error silently โ always log or print the error for visibility
- Not setting a timeout โ without a timeout, your script may hang forever waiting for a connection
- Retrying immediately without delay โ this can overwhelm a struggling server or network
- Assuming all connection failures are the same โ distinguish between DNS failures, refused connections, and network unreachable errors using the exception's args or response attribute
โ Summary
Catching requests.exceptions.ConnectionError is a fundamental skill for building robust Python scripts that interact with external services. By handling network failures gracefully, you prevent your scripts from crashing and gain visibility into infrastructure anomalies. Always combine this with proper logging, retry logic, and timeout settings to create production-ready code that can withstand real-world network conditions.
Interactive Views
You are currently in ๐ All-in-One mode. Use the tabs at the top to switch to ๐ Theory Only or ๐ป Code Only views.
This exception is raised when a network connection cannot be established to the target server, allowing engineers to handle network failures gracefully.
๐งช Example 1: Basic ConnectionError catch with a fake URL
This example shows how to catch a connection error when the server does not exist.
import requests
try:
response = requests.get("https://this-domain-does-not-exist-12345.com")
except requests.exceptions.ConnectionError:
print("Connection failed โ server not reachable")
๐ค Output: Connection failed โ server not reachable
๐งช Example 2: Catching ConnectionError with a timeout
This example demonstrates that a timeout is a different exception, not a ConnectionError.
import requests
try:
response = requests.get("https://httpbin.org/delay/10", timeout=2)
except requests.exceptions.ConnectionError:
print("ConnectionError caught")
except requests.exceptions.Timeout:
print("Timeout caught โ this is NOT a ConnectionError")
๐ค Output: Timeout caught โ this is NOT a ConnectionError
๐งช Example 3: Distinguishing between ConnectionError and other exceptions
This example shows how to handle ConnectionError separately from other request failures.
import requests
url = "https://httpbin.org/status/500"
try:
response = requests.get(url)
response.raise_for_status()
except requests.exceptions.ConnectionError:
print("Could not connect to the server")
except requests.exceptions.HTTPError:
print("Server responded with an error status code")
๐ค Output: Server responded with an error status code
๐งช Example 4: Retrying after a ConnectionError
This example shows a simple retry pattern when a connection fails temporarily.
import requests
import time
url = "https://httpbin.org/status/200"
max_retries = 3
for attempt in range(max_retries):
try:
response = requests.get(url, timeout=5)
print("Success on attempt", attempt + 1)
break
except requests.exceptions.ConnectionError:
print("Attempt", attempt + 1, "failed โ retrying in 2 seconds")
time.sleep(2)
else:
print("All retries exhausted โ connection still failing")
๐ค Output: Success on attempt 1
๐งช Example 5: Logging the full error details for debugging
This example shows how to capture and display the underlying error message from a ConnectionError.
import requests
try:
response = requests.get("https://localhost:9999", timeout=3)
except requests.exceptions.ConnectionError as error:
print("ConnectionError details:")
print(" Type:", type(error).__name__)
print(" Message:", str(error))
๐ค Output: ConnectionError details: / Type: ConnectionError / Message: HTTPConnectionPool(host='localhost', port=9999): Max retries exceeded with url: / (Caused by NewConnectionError('
Comparison Table
| Scenario | Exception Type | Typical Cause |
|---|---|---|
| Server does not exist | ConnectionError | DNS resolution failure or unreachable host |
| Server refuses connection | ConnectionError | Port closed or service not running |
| Request takes too long | Timeout | Server slow or network congestion |
| Server returns error status | HTTPError | 4xx or 5xx response code |
| Invalid URL format | InvalidURL | Malformed URL string |