Free tools Windows power users keep installed
One-click scans. No signup required.
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 Guzzle’s timeout request option to a positive number of seconds. It limits the complete request. Use it on one request for a local override, or set it when constructing the client for a default. Catch TransferException because a timeout normally produces no HTTP response.
The direct implementation
This request fails through Guzzle’s transfer-exception path if the operation has not completed within five seconds:
<?php
use GuzzleHttpClient;
use GuzzleHttpExceptionTransferException;
$client = new Client();
try {
$response = $client->request('GET', 'https://example.com/api', [
'timeout' => 5.0,
]);
echo $response->getBody();
} catch (TransferException $e) {
// Log the failure and return an application-specific error.
error_log('HTTP request failed: ' . $e->getMessage());
}
The value is expressed in seconds, and a floating-point value such as 0.5 is valid. The documented default for timeout is 0, which means no total deadline. A finite value is usually safer for web requests, queue workers and command-line jobs whose callers have a latency budget.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteUnderstand Guzzle’s three timeout scopes
These options do not measure the same part of a transfer. Select the narrowest scope that matches the failure you need to prevent.
#1 Best Overall
| Option | Scope | Documented default | Important qualification |
|---|---|---|---|
timeout |
The complete request | 0 (indefinite) |
Use a positive number to impose a total cap. It can be set per request or as a client default. |
connect_timeout |
Connection establishment | 0 (indefinite) |
Support depends on the active transfer handler; the built-in cURL handler supports it. |
read_timeout |
One read from a streamed response body | Not a total-request setting | It applies when stream is enabled and does not cap the entire download. |
A total timeout and a connection timeout can be used together. The connection limit controls how long connection setup may take, while timeout remains the overall ceiling. A custom handler must actually implement the options you rely on; Guzzle passes transfer settings to the handler rather than enforcing every setting itself.
Set a default for every request
Pass timeout to the client constructor when all requests made by that client should share a baseline deadline:
<?php
use GuzzleHttpClient;
$client = new Client([
'timeout' => 5.0,
]);
$response = $client->request('GET', 'https://example.com/api');
Guzzle clients are immutable. Configure a different default by constructing another client; do not expect to mutate the existing client’s defaults after creation. A request-level option can override the client default for an operation that legitimately needs more or less time:
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →$response = $client->request('GET', 'https://example.com/slow-report', [
'timeout' => 30.0,
]);
Keep separate clients when different parts of an application have clearly different latency budgets. This makes the policy visible at construction and avoids accidentally relaxing a short deadline for unrelated calls.
Rank #2
Add a connection bound when connection setup is the problem
Use connect_timeout when a request can spend too long establishing a network connection. It is measured in seconds:
$client = new GuzzleHttpClient([
'timeout' => 10.0,
'connect_timeout' => 2.0,
]);
The stable documentation identifies the built-in cURL handler as supporting connect_timeout. If your application selects a custom handler, verify that handler’s transfer-option support before depending on the setting. A connection timeout is not a replacement for a total timeout: a server can accept a connection and then take too long to produce the response.
Use read_timeout only for streamed bodies
For a streamed response, read_timeout limits an individual read operation. It is useful when your code consumes the body incrementally, but it does not define how long the complete request or download may take.
<?php
use GuzzleHttpClient;
use GuzzleHttpExceptionTransferException;
$client = new Client();
try {
$response = $client->request('GET', 'https://example.com/large-file', [
'stream' => true,
'timeout' => 120.0,
'read_timeout' => 10.0,
]);
$body = $response->getBody();
while (!$body->eof()) {
$chunk = $body->read(8192);
if ($chunk !== '') {
// Process or write this chunk.
}
}
} catch (TransferException $e) {
error_log('Streaming request failed: ' . $e->getMessage());
}
Here, timeout remains the whole-operation limit, while each blocking read has its own limit. Without stream => true, read_timeout does not describe the normal buffered-response path.
Choose a value from the caller’s latency budget
Guzzle’s documentation defines the units and scopes but does not prescribe one universally correct number. Set the deadline from the surrounding operation:
- For a browser-facing request, leave enough time for a normal response while protecting the page’s response-time budget.
- For a queue job, include the job’s visibility or worker deadline so a timed-out attempt can finish before the job is redelivered.
- For a batch or report download, use a larger total value and consider streaming rather than buffering the entire body.
- For a connection to an optional dependency, use a short connection limit so an unavailable host does not consume the whole application deadline.
A value of 0 is unbounded. That may be appropriate for a deliberately long-lived operation, but it means a stalled transfer can wait indefinitely. Use a positive value whenever the caller requires a finite cap.
Handle failures correctly
Catch a suitable Guzzle transfer exception at the application boundary. A timeout is a transfer failure, not an HTTP status such as 408 or 504, and there may be no response object to inspect. Convert it into the error format your application exposes, and log enough context to identify the operation and configured deadline.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →try {
$response = $client->request('GET', $url, ['timeout' => 8.0]);
$status = $response->getStatusCode();
} catch (GuzzleHttpExceptionTransferException $e) {
// The request may have failed before an HTTP response existed.
return ['ok' => false, 'error' => 'upstream_unavailable'];
}
Retries need an explicit policy. Retry only operations that are safe to repeat, or use the upstream service’s idempotency mechanism for operations that create or change data. A timeout leaves the outcome unknown: the remote server might have processed the request even though the client stopped waiting. Bound the number of attempts and include backoff so a slow dependency is not amplified into a retry storm.
Rank #4
Keep TLS verification enabled
Timeout configuration does not require changing certificate verification. Guzzle enables the verify option by default, and its documentation warns that disabling verification is insecure. Keep verification enabled while diagnosing slow connections or transfers; setting verify => false is not a valid timeout workaround.
Common mistakes and fixes
The request still waits forever
- Cause: The effective
timeoutis0, or the option was placed on a different request/client than the one being used. - Fix: Set a positive value on the actual request, or construct the client with a finite default. Log the selected policy at the boundary where the request is made.
You catch an HTTP exception but not the timeout
- Cause: A timeout can occur before any HTTP response exists.
- Fix: Catch
TransferException(or an appropriate subclass) around the request and handle the failure without assuming a status code.
connect_timeout appears ineffective
- Cause: The active handler does not support that transfer option, or the delay occurs after connection establishment.
- Fix: Confirm the handler configuration and distinguish connection delay from slow response or body reads. Keep a total
timeoutas the final guard.
read_timeout has no effect
- Cause: The response is not being streamed.
- Fix: Enable
stream => trueand read the body incrementally. Usetimeoutwhen you need a complete-operation limit.
A retry duplicated a write
- Cause: The client timed out after the server received the request, so the retry submitted the same operation again.
- Fix: Restrict automatic retries to idempotent operations or send an idempotency key understood by the API. Record the attempt outcome as unknown when necessary.
Someone disabled certificate checks while debugging
- Cause: A TLS failure was mistaken for a timeout problem.
- Fix: Restore the default verification behavior and diagnose certificate, hostname or trust-store issues separately.
Test the policy before relying on it
- Exercise a successful endpoint and confirm the request completes under the configured deadline.
- Use a controlled endpoint or local test server that deliberately delays connection, headers or body reads. Test each phase separately rather than treating every delay as the same failure.
- Record elapsed time, the option values, handler choice and exception message. A measured duration close to the configured value indicates the deadline fired; a much shorter failure may indicate DNS, TLS or another transfer error.
- Test the retry path with an idempotent operation and verify that your application returns a stable error when all attempts fail.
- For streamed downloads, pause between body chunks and confirm that individual read failures and the overall deadline are handled as separate conditions.
Do not infer a universal “correct” timeout from one test. Production latency varies by operation and dependency, so review the value against the caller’s deadline and the service’s normal response characteristics.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
If your testing or automation task also needs a clean screenshot of a URL, ScreenshotNeo provides a single HTTP call instead of maintaining browser-launch code. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets. Bot checks, blank pages, failed loads, timeouts and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients.
See the ScreenshotNeo API documentation for authentication and options. A one-call example in PHP is:
<?php
$params = http_build_query([
'access_key' => 'YOUR_API_KEY',
'url' => 'https://stripe.com',
]);
$data = file_get_contents('https://api.screenshotneo.com/v1/shot?' . $params);
file_put_contents('shot.webp', $data);
The equivalent cURL command is:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
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)
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}`);
Every feature is available on every plan: the free plan includes 1,000 screenshots per month with no card, and paid plans start at $5 for 3,000. Create a free ScreenshotNeo account to try it.
Final checklist
- Set a positive
timeoutin seconds for a finite total deadline. - Use a constructor default for a client-wide policy and a request option for an exception.
- Add
connect_timeoutonly when connection setup needs its own bound and the handler supports it. - Use
read_timeoutwith streamed responses; it limits individual reads, not the whole request. - Catch
TransferException, because a timeout may provide no HTTP response. - Keep TLS verification enabled and make retries safe for the operation being repeated.
Frequently Asked Questions
Can a timed-out request still have been processed by the server?
Yes. The timeout limits how long the client waits; it does not prove that the remote server stopped work. Treat the result of a timed-out write as uncertain and use idempotency controls before retrying.
Should I use one timeout for every endpoint?
Not necessarily. Set each client or request’s deadline from the caller’s latency budget and the operation’s behavior; a streamed report and a short dependency lookup usually need different policies.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteDoes a timeout change Guzzle’s certificate validation?
No. Timeout options and TLS verification are separate. Leave verification enabled while diagnosing transfer timing.
Quick Recap
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.

