Start with cURL’s result when a page downloaded through a proxy looks incomplete. A short response, a failed transfer and a complete block page need different explanations.

With CURLOPT_RETURNTRANSFER enabled on the existing configured handle:

$body = curl_exec($ch);
if ($body === false) {
    throw new RuntimeException(curl_error($ch), curl_errno($ch));
}

$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$downloaded = curl_getinfo($ch, CURLINFO_SIZE_DOWNLOAD_T);
$declared = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T);

Collect these before releasing the handle. The strict comparison distinguishes transport failure from successful bodies such as an empty string or "0". HTTP error statuses are not automatically curl_exec failures, so interpret status as well.

The downloaded counter excludes headers. The declared value comes from Content-Length and is -1 when that size is unknown. A response can legitimately omit Content-Length; an unknown value is not a truncated-file diagnosis.

Automatic content decoding introduces another distinction. Content-Length commonly describes the compressed representation, while the PHP string can contain decompressed bytes. Comparing strlen($body) to that header then compares different representations.

cURL can report CURLE_PARTIAL_FILE when the transfer violates an expected size. Preserve that error rather than treating any nonempty output as success. Conversely, a successful transfer with a small 200 response may be the entire page the origin or proxy chose to return.

Finally check the required content. HTML fetched by cURL does not execute JavaScript to populate the page. Missing browser-rendered sections can be absent from the original response even when every transmitted byte arrived.

Ũhoro ũhĩtĩte