Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan Now×
Skip to content
World desk4 min

Downloaded PDF Is Only 1 KB in Python: Find the Real HTTP Response

A tiny .pdf file is not necessarily a corrupt PDF. Inspect the response status, final URL, headers and magic bytes to distinguish an error page, access problem and incomplete transfer.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A 1 KB file is not automatically a damaged PDF. Your script may have saved an HTML error or login page, a redirect response, or only part of the file. Inspect the HTTP status, final URL, headers, and first bytes before changing libraries or adding request headers.

Diagnose the response before diagnosing the PDF

The filename and .pdf extension describe what you called the output, not what the server returned. A small response can be an access-denied page, authentication form, redirect endpoint, incomplete transfer, or an actual (but unusually small) document.

  1. Check the status code and final URL.
  2. Inspect Content-Type and Content-Length.
  3. Examine the first bytes or a short text preview.
  4. Compare the bytes written with a trustworthy declared length, when one exists.

Requests documents checking status_code or calling raise_for_status(); receiving a response object alone does not prove that the request succeeded.

A safe Requests download pattern

Stream the body, open the destination in binary mode, and close the response reliably:

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

url = "https://example.com/file.pdf"

with requests.get(url, stream=True, timeout=30) as response:
    response.raise_for_status()
    print("Final URL:", response.url)
    print("Status:", response.status_code)
    print("Content-Type:", response.headers.get("Content-Type"))
    print("Content-Length:", response.headers.get("Content-Length"))

    with open("download.pdf", "wb") as output:
        for chunk in response.iter_content(chunk_size=64 * 1024):
            if chunk:
                output.write(chunk)

Requests recommends iter_content() for streamed downloads and writing chunks to a file opened with 'wb'. It handles gzip and deflate transfer encodings. By contrast, Response.raw exposes the raw stream and is not the usual file-writing interface.

With stream=True, Requests obtains the headers first and leaves the connection open until you consume the body or close the response. The with statement ensures closure even when an error occurs.

Inspect what the short file contains

Run a separate diagnostic request, or inspect the saved bytes:

from pathlib import Path

path = Path("download.pdf")
data = path.read_bytes()
print("Bytes written:", len(data))
print("First 16 bytes:", data[:16])
print("Text preview:", data[:300].decode("utf-8", errors="replace"))

A normal PDF begins with the ASCII signature %PDF-. If the preview starts with <!DOCTYPE html>, <html>, or a message such as “access denied,” you saved a web page rather than a PDF. A URL that ends at a sign-in page can look successful at the HTTP level while still returning HTML. If the first bytes do start with %PDF-, compare the written length with the server’s declared length and investigate truncation.

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.

Do not treat a missing or incorrect Content-Length as proof either way. Chunked responses may omit it, and a server can send an inaccurate value.

Interpret the common failure branches

HTML error or access page

A 4xx or 5xx status should be handled by raise_for_status(). Some services nevertheless return a 200 status for an application-level error page. Confirm the final URL, then use the legitimate document URL and the required authentication or session. A browser-style User-Agent is not a general fix for permissions, expiring links, cookies, or signed URLs.

Redirect or login endpoint

Print response.url after redirects. If it points to a different host, a sign-in route, or a download handler rather than the document, obtain an authorized URL or preserve the required session. Do not assume that the original URL’s extension reflects the final response.

Partial transfer

If the bytes begin with %PDF- but are fewer than a reliable Content-Length, the connection may have been interrupted or the server may have supplied inconsistent metadata. Record both values, retry with a stable connection, and investigate the server or proxy. The fact that a file was created does not establish that the body was complete.

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

Unexpected content type

application/pdf is the expected media type, but headers are hints rather than proof. Conversely, some servers mislabel valid files. Use the status, final URL, header values, and magic bytes together.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Using Python’s standard library instead

urllib.request.urlretrieve() provides a direct URL-to-file helper:

from urllib.request import urlretrieve

urlretrieve("https://example.com/file.pdf", "download.pdf")

Python 3.13 documentation says urlretrieve() raises ContentTooShortError when it detects fewer bytes than a supplied Content-Length, such as after an interrupted download. If the server sends no Content-Length, it cannot perform that size check and simply returns the file. The exception still does not prove that a file is a valid PDF, nor does it prove a server’s length header is correct.

Requests or urlretrieve()?

Need Requests urllib.request.urlretrieve()
Stream and process chunks Use iter_content() with explicit chunk size and binary output. Direct file-copy helper; less control over the body-processing loop.
Inspect response details Exposes status, final URL, headers, and streamed content directly. Convenient for copying, but response inspection is less central to the helper.
Short-read check Compare written bytes with a usable expected length yourself. Raises ContentTooShortError when a supplied length reveals a short read; no length means no check.
Connection cleanup Consume the body or close the response; a context manager handles this. Managed by the helper.

A practical checklist

  • Print the HTTP status and final URL.
  • Call raise_for_status() before writing the file.
  • Print Content-Type and Content-Length.
  • Save with binary mode and streamed chunks.
  • Check that the first bytes are %PDF-.
  • Compare actual and declared lengths only when the declared length is usable.
  • If the body is HTML, fix the URL, authentication, session, or access requirement rather than repeatedly changing download code.
  • If the body is a truncated PDF, retry and examine transfer interruptions or server-side length errors.

Why the 1 KB figure cannot identify the cause

The title supplies no URL, status code, headers, or bytes, so no single explanation is established. A historical Requests issue opened on 27 June 2019 described 2,583 returned bytes against a declared Content-Length of 66,892,906—an example of a possible partial transfer or server metadata problem, not a frequency statistic or a diagnosis of every 1 KB download.

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

Inspecting the actual response is therefore the decisive next step: it tells you whether to correct access, follow the proper endpoint, or recover an incomplete transfer.

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

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

More from the Wire

  1. Shenzhen desk3 min
    HONOR Expands Beyond Smartphones With Humanoid Robot RevealHONOR said it unveiled its first humanoid robot at MWC 2026 and named shopping assistance, workplace inspections, and supportive companionship as intended uses. Later Robotics D1 claims and a reported…
  2. Cupertino desk5 min
    Apple Unveils AirPods Max 2: The Upgrade That Should Have Happened Years AgoAirPods Max 2 adds H2-powered audio features and Apple claims up to 1.5× more effective ANC, but its design, Smart Case, and 20-hour battery rating are unchanged. Wired lossless audio…
  3. Cupertino desk4 min
    Apple’s OLED Touch MacBooks Are Coming—but the Dynamic Island Is the Real GambleApple has not announced an OLED touchscreen MacBook, but reports point to high-end models arriving in late 2026 or early 2027. The reported Mac Dynamic Island could be useful, but…
Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.