Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

requests.exceptions.ReadTimeout means your Python client connected (or got far enough to wait for a response), but the server did not send data within the configured read interval. Fix it by setting an explicit timeout—preferably separate connect and read budgets—then investigate the endpoint, network path, or server if the delay is legitimate. Add bounded retries only for operations that are safe to repeat.

What “Read timed out” means

Requests waits indefinitely when you omit timeout. That is unsafe for production code because a stalled connection can leave a worker, job, or web request blocked forever. A read timeout is an inactivity limit: after the request is sent, Requests waits only the configured number of seconds for the server to send response data. It is not a maximum duration for the complete download. A server that continuously sends bytes can therefore run for a long time without reaching the read timeout.

ConnectTimeout is different: it occurs while establishing the connection. DNS lookup, TCP connection, proxy negotiation, and TLS setup can all consume the connect budget. Catching the broader requests.exceptions.Timeout is useful when the application should handle either phase uniformly.

Set an explicit connect and read timeout

Use a tuple when the two phases need different budgets. In this example, Requests has 3.05 seconds to establish the connection and 27 seconds of inactivity tolerance while waiting for response bytes.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import requests

url = "https://api.example.com/data"

try:
    response = requests.get(
        url,
        timeout=(3.05, 27),  # connect timeout, read timeout
    )
    response.raise_for_status()
except requests.exceptions.ReadTimeout:
    # The server stopped sending bytes within the read interval.
    handle_timeout()
except requests.exceptions.Timeout:
    # Includes ConnectTimeout and other Requests timeout subclasses.
    handle_timeout()

Replace handle_timeout() with your application’s fallback, logging, or error response. Always call raise_for_status() after a response so HTTP 4xx and 5xx responses are handled as application or server errors rather than mistaken for timeout problems.

Scalar versus tuple timeouts

Setting Meaning When to use
timeout=10 Uses the same value for connection and response-read inactivity. Simple calls where one budget is reasonable for both phases.
timeout=(3.05, 27) Separates connection setup from read inactivity. Most production API calls; tune each phase independently.
No timeout No client-side timeout is applied by Requests. Avoid in production.

Choose values that match the operation

  • Connect timeout: allow for DNS, TCP, proxy, and TLS setup on the network where the program runs. A value that is too short creates failures on a slow or distant network; a value that is too long delays recovery from an unreachable host.
  • Read timeout: allow the expected server latency between bytes. A fast JSON endpoint usually needs a different value from a report-generation endpoint.
  • Streaming: the read timer concerns inactivity between bytes. It does not cap total transfer time. If you need a wall-clock limit, enforce one at the application or job level in addition to Requests’ timeout.

Increasing the read value only makes the client wait longer for the next byte. It does not repair DNS, firewall, TLS, proxy, server overload, or an endpoint that never produces a response.

A reliable diagnosis sequence

  1. Identify the exception. Log whether it is ReadTimeout, ConnectTimeout, or another Timeout. Record the URL (without secrets), HTTP method, connect and read values, elapsed time, and whether any response bytes arrived.
  2. Reproduce minimally. Run a small request from the same machine, container, proxy, credentials, and network path. This distinguishes an application issue from an environment-specific route, DNS, TLS, or firewall problem.
  3. Check the server side. Inspect application, load-balancer, and upstream logs for the request time. A slow database query, overloaded worker, or dependency may be the actual cause.
  4. Separate latency from inactivity. If the endpoint is healthy but takes a long time before producing its first byte, increase the read budget only after confirming that behavior is expected. If it streams regularly, a read timeout may never fire even though the operation is very long.
  5. Validate HTTP status handling. A 400, 401, 403, 404, or other 4xx is not fixed by a larger timeout. Read the response body and correct the request, authentication, URL, or permissions.
  6. Add bounded retries only for transient cases. Use backoff and a finite attempt count, and ensure the operation is safe to repeat.

Retry timed-out requests safely

Requests’ HTTPAdapter defaults max_retries to zero. Configure urllib3’s Retry explicitly when transient connection, read, or status failures should be retried.

from requests import Session
from requests.adapters import HTTPAdapter
from urllib3.util import Retry

retry = Retry(
    total=3,
    connect=3,
    read=3,
    backoff_factor=0.5,
    status_forcelist=(429, 500, 502, 503, 504),
    allowed_methods=frozenset({"GET", "HEAD", "OPTIONS"}),
)

session = Session()
session.mount("https://", HTTPAdapter(max_retries=retry))

response = session.get(
    "https://api.example.com/data",
    timeout=(3.05, 27),
)
response.raise_for_status()

This configuration is an implementation example, not a universal tuning prescription. Retry only idempotent or otherwise safely repeatable operations. GET, HEAD, and OPTIONS are included here because repeating them normally does not create a second business transaction. Do not blindly retry a payment, order creation, upload, or other non-idempotent write; inspect the API’s semantics and use an idempotency key or another deduplication strategy when the service supports it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Retries multiply work and can worsen an outage. Keep the attempt count finite, use backoff, and expose the final failure to monitoring. Consider the service’s rate-limit guidance before retrying 429 responses.

Session-wide timeout policy

A timeout passed to one call is not automatically inherited by other calls. For a larger application, wrap requests in a small helper or use a custom adapter so every request has an explicit policy. Keep the timeout visible at the call boundary when different endpoints have materially different latency expectations. A session can centralize connection pooling and retry behavior, while each call can still supply its own connect/read tuple.

import requests

session = requests.Session()

def get_json(url, *, timeout=(3.05, 27), **kwargs):
    response = session.get(url, timeout=timeout, **kwargs)
    response.raise_for_status()
    return response.json()

try:
    payload = get_json("https://api.example.com/data")
except requests.exceptions.ReadTimeout:
    # Report the endpoint and timeout policy, then choose a fallback.
    payload = None

Common symptoms and fixes

Symptom Likely cause Action
ReadTimeout after a consistent interval No response bytes arrived within the read budget. Check server latency and upstream dependencies; then tune the read value if the delay is expected.
ConnectTimeout Connection setup exceeded its budget. Test DNS, proxy, firewall, routing, and TLS from the same host; adjust the connect value only when the path is valid but slow.
Timeout only in production Different egress IP, proxy, DNS, firewall, load, or credentials. Reproduce from the production network and compare client and server logs.
Increasing timeout changes nothing The request is rejected, malformed, blocked, or the server never sends data. Capture status and response details, verify the URL and authentication, and inspect server logs.
Occasional timeouts during traffic spikes Transient overload or dependency latency. Use bounded, backoff retries for safe methods and fix capacity or slow dependencies.
Large download runs for a long time without timing out Bytes keep arriving, so the inactivity threshold is not crossed. Use streaming carefully and add a separate application-level total-duration limit if required.

What to log without leaking secrets

  • Exception class and message.
  • HTTP method and a sanitized URL.
  • Connect and read timeout values.
  • Elapsed time and retry attempt.
  • Whether a response was received and its status code.
  • Host, proxy or egress path, and a correlation ID when available.

Do not log authorization headers, cookies, API keys, or sensitive request bodies. Correlate the client timestamp with server and proxy logs to determine which hop stopped making progress.

Or skip the browser setup

If the timeout is happening while you are trying to obtain a visual record of a web page, ScreenshotNeo provides a direct screenshot API instead of requiring you to operate a browser. It accepts a URL and returns PNG, JPEG, WebP, or PDF. Before capture it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Python:

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

cURL:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

See the ScreenshotNeo documentation for request options. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.

FAQ

Does a read timeout mean the server is down?

No. It means no response bytes arrived during the client’s read interval. The server may be healthy but slow, blocked on a dependency, or unreachable only from your network path.

Can I use one timeout for every request?

You can, but separate connect and read values make failures easier to interpret and let you match the policy to each endpoint’s behavior.

Will retries guarantee delivery?

No. They provide additional bounded attempts for transient failures. They cannot correct invalid requests or make an unsafe write safe to repeat.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Frequently Asked Questions

Does a read timeout mean the server is down?

No. It means no response bytes arrived during the client’s read interval; the server may be slow or the network path may be blocking progress.

Can I use one timeout for every request?

Yes, but a separate connect/read tuple usually gives better control and diagnosis.

Will retries guarantee delivery?

No. Retries add bounded attempts for transient failures and must be limited to operations that are safe to repeat.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.