← Back to Blog
Code Snippets August 11, 2026

Python: Robust File Download with Progress, Retry & SHA-256

💻 Code Snippet — Aug 11, 2026

Python: Robust File Download with Progress, Retry & SHA-256

The naive requests.get().content gives you no progress, no retry, and no integrity check. This covers the three things that break in production:

import hashlib, requests, time, sys
from pathlib import Path

def download_file(url, dest, expected_hash=None, max_retries=3):
    dest = Path(dest)
    dest.parent.mkdir(parents=True, exist_ok=True)
    delay = 1.0
    for attempt in range(1, max_retries + 1):
        try:
            r = requests.get(url, stream=True, timeout=(10, 60),
                headers={"User-Agent": "Downloader/1.0"})
            if 400 <= r.status_code < 500:
                r.raise_for_status()

            total = int(r.headers.get("Content-Length", 0))
            downloaded = 0
            sha = hashlib.sha256()

            with open(dest, "wb") as f:
                for chunk in r.iter_content(8192):
                    if not chunk: continue
                    f.write(chunk)
                    sha.update(chunk)
                    downloaded += len(chunk)

            if expected_hash:
                actual = sha.hexdigest()
                if actual.lower() != expected_hash.lower():
                    dest.unlink()
                    raise ValueError("Hash mismatch!")
            return dest

        except requests.exceptions.HTTPError:
            if 400 <= r.status_code < 500: raise
        except requests.exceptions.RequestException:
            if attempt < max_retries:
                time.sleep(delay); delay *= 2
            else: raise
    if dest.exists(): dest.unlink()


Why it works:
  • Streaming 8KB chunks — never loads full file into RAM

  • Exponential backoff retry for flaky connections

  • Stops on 4xx (won't be fixed by retrying)

  • Incremental SHA-256 — verify without loading file

  • Auto-cleans partial downloads on failure


💡 Requires only requests. Bookmark this.