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.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Set a timeout explicitly on every Requests call to an external service. Use one number when the same limit should apply to connecting and waiting for response data, or a tuple such as (3.05, 27) to set those limits separately. Catch requests.exceptions.Timeout or its more specific subclasses to handle timeouts. Crucially, Requests’ timeout is not a deadline for the entire download: it limits how long the socket can go without receiving data.

Set a timeout on each request

Requests does not time out by default. If a server or network connection stalls, a call without a timeout can wait indefinitely. The Requests Quickstart advises using the parameter in nearly all production requests.

Pass timeout to the request method you call, such as get, post, or request:

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.
import requests

response = requests.get(
    "https://api.example.com/data",
    timeout=10,
)
response.raise_for_status()
data = response.json()

Here, 10 is an example, not a universal setting. Choose values for the service you call and the time your own program can afford to wait. A fast internal service and a slow report-generation endpoint may need different limits.

Choose one timeout or a tuple

  • timeout=10 sets both the connection timeout and the read timeout to 10 seconds.
  • timeout=(3.05, 27) sets the connection timeout to 3.05 seconds and the read timeout to 27 seconds.

The tuple is useful when establishing a connection should be quick but the service may take longer to return data. Its values configure different phases; they do not add up to a guaranteed maximum duration for the whole request.

Understand what Requests’ timeout actually limits

The timeout is based on socket inactivity: how long the underlying socket can go without receiving data. It is not a total wall-clock limit on the request or a cap on the time required to download the complete response. A server that periodically sends data may keep a request active beyond the configured read timeout.

Connection and read timeouts are not strict end-to-end deadlines either. For example, a host can resolve to multiple IP addresses; trying more than one address can make the effective connection time longer than the configured connect timeout. Treat the values as controls on particular network waits, not as a promise that your function will return within a fixed number of seconds.

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

Account for the caller’s latency budget

Choose timeout values by considering the slowest acceptable service response and how much time remains for the rest of the caller’s work. If a web request, job runner, or user-facing process has an overall time budget, the Requests timeout alone does not enforce it. Avoid setting a large read timeout merely to approximate a deadline: it still measures inactivity between received data, not total elapsed time.

Streaming separates receiving headers from consuming the body

With stream=True, receiving the response and consuming its body are distinct stages in your workflow. The socket’s inactivity behavior still matters while the body is read. Ensure your application handles errors during body consumption too; successfully receiving a response object does not mean every later read must complete without a timeout.

Catch timeout exceptions without confusing them with HTTP errors

Requests provides requests.exceptions.Timeout as a common superclass for connection and read timeouts. Catch it when both should receive the same handling; catch a specific subclass when the recovery action depends on which phase failed.

import requests

try:
    response = requests.get(
        "https://api.example.com/data",
        timeout=(3.05, 27),
    )
    response.raise_for_status()
except requests.exceptions.ConnectTimeout:
    # The connection could not be established within its timeout.
    raise
except requests.exceptions.ReadTimeout:
    # No response data arrived within the read timeout interval.
    raise
except requests.exceptions.Timeout:
    # Common handling for either timeout subtype.
    raise

The final Timeout handler is useful when the two specific cases share a fallback, such as recording a timeout and returning a controlled error. In this example, the earlier handlers distinguish the causes; because each re-raises, the broad handler is not reached for those two exception classes. In a real application, either handle the specific cases and omit the broad one, or use the broad handler alone if the distinction does not matter.

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

Keep transport failures separate from unsuccessful status codes

  • ConnectTimeout means connection establishment did not complete within the connect timeout. Requests documents this exception as safe to retry.
  • ReadTimeout means no response data arrived within the read timeout interval.
  • Timeout is the common superclass for both.
  • ConnectionError covers broader network problems, including DNS failures and refused connections; these are not the same as an HTTP response with an unsuccessful status.
  • HTTPError is raised by raise_for_status() for an unsuccessful HTTP status. It is distinct from a timeout.

Handle the HTTP result as well as transport exceptions. A server can return an error status and a JSON response body; decoding that JSON does not establish that the HTTP operation succeeded. Call raise_for_status() when an unsuccessful status should follow your error path, or explicitly inspect response.status_code.

Retry deliberately, not automatically

Requests does not retry failed connections by default. For granular retry behavior, the Requests documentation describes attaching urllib3.util.Retry to an HTTPAdapter on a session. A retry policy can set a total retry count, a backoff, selected status codes, and the HTTP methods eligible for retries.

Those settings should reflect the operation, not simply the desire to avoid exceptions. A timeout can happen after the server has received the request. Repeating a write or other non-idempotent operation may therefore perform an action twice even though the client never received the first response. Requests documents ConnectTimeout as safe to retry, but that is not a blanket guarantee that every timeout or every application operation is safe to repeat.

Configure the retry scope to match the work

  • Decide which methods are safe for your application to repeat. Restrict retries rather than enabling them indiscriminately.
  • Choose a finite retry count and backoff appropriate to the caller’s latency budget. Each attempt and wait can extend total elapsed time; a Requests timeout is not a total deadline.
  • Select status codes deliberately if the policy retries responses as well as connection failures.
  • For operations that can create or change data, use application-level safeguards where available before retrying after an ambiguous timeout.

The adapter reference distinguishes retrying connection setup failures from requests whose data has already made it to the server. A retry policy cannot infer whether an application-side operation is safe; that depends on the endpoint and your program.

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

Troubleshoot common timeout and request failures

Symptom What it means What to do
The call appears to hang indefinitely No timeout was supplied, and Requests has no default timeout. Pass an explicit timeout on the request. Select values based on the service and caller’s needs.
ConnectTimeout Connection establishment did not complete within its configured interval. Check whether the destination is reachable and whether the connect limit suits the service. Retry only when the operation and retry policy make that safe.
ReadTimeout No response data arrived within the configured read interval. Check whether the service normally needs longer to begin or continue sending data. Adjust the read value only if the caller can tolerate the delay.
ConnectionError A broader network problem occurred, such as DNS failure or a refused connection. Investigate name resolution, destination availability, and the network path; do not treat this automatically as an HTTP status error.
HTTPError after raise_for_status() The server returned an unsuccessful HTTP status; this is not a socket timeout. Handle the status and any useful response body according to the endpoint’s behavior.
A streamed response fails while the body is being read The response body is consumed after the initial request stage, and socket inactivity still applies. Handle exceptions around the body-reading work as well as around the request itself.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Use a timeout policy that fits the operation

For a simple read from an API, begin with an explicit timeout and distinguish timeout handling from HTTP status handling. Use a tuple if connection setup and response waiting have different acceptable limits. If retries are necessary, add a deliberate policy rather than assuming Requests will retry, and account for the time spent across attempts.

For a state-changing request, consider the ambiguous case: a timeout tells the client it did not receive data in time, not necessarily that the server did nothing. Avoid blind retries unless repeating that operation is safe. For a streamed download, also plan for failures during body consumption instead of treating receipt of headers as completion.

Or skip the browser setup

If your goal is to get a website screenshot rather than to build a browser-capture workflow, ScreenshotNeo offers a screenshot API and MCP server. One GET request can return an image or PDF; the API accepts a URL and supports PNG, JPEG, or WebP output. Its Python example uses Requests with an explicit 90-second timeout:

import requests

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

See the ScreenshotNeo API documentation for request options and setup. The service removes cookie or consent banners, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in headers. Its MCP server provides screenshot and page-information tools for AI agents.

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

The Free plan includes 1,000 shots per month without a card; paid plans start at $5 for 3,000 shots. Sign up for ScreenshotNeo’s free plan.

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.