Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes
Sponsored Reserved space — layout preview until AdSense is connected

Download Files from Internet with Progress Bar in Python

Download a file from the internet while displaying a text progress bar in the terminal.

Medium Python 3.9+ Jun 27, 2026 Files & data 1 views 0 copies

Python code

23 lines
Python 3.9+
import urllib.request
import sys

def download_with_progress(url, filename):
    """Download a file with a simple text progress bar."""
    def report_hook(block_count, block_size, total_size):
        downloaded = block_count * block_size
        if total_size > 0:
            percent = min(100, int(downloaded * 100 / total_size))
            bar = '#' * (percent // 2) + '-' * (50 - percent // 2)
            sys.stdout.write(f'\r[{bar}] {percent}%')
            sys.stdout.flush()
        else:
            sys.stdout.write(f'\rDownloaded {downloaded} bytes')
            sys.stdout.flush()

    print(f'Downloading {url}...')
    urllib.request.urlretrieve(url, filename, reporthook=report_hook)
    print(f'\nDownload complete: {filename}')

if __name__ == '__main__':
    url = 'https://www.python.org/static/img/python-logo.png'
    download_with_progress(url, 'python_logo.png')

Output

stdout
Downloading https://www.python.org/static/img/python-logo.png...
[##################################################] 100%
Download complete: python_logo.png

How it works

This function uses urllib.request.urlretrieve which accepts a reporthook callback. Each time a chunk is downloaded, report_hook is called with the block count, block size, and total file size. The function calculates the download percentage and builds a textual progress bar by writing to stdout using \r to overwrite the current line. If the total size is unknown, it displays the byte count instead. Once the download finishes, a completion message is printed.

Common mistakes

  • Forgetting to flush stdout, causing the progress bar to not update in real time.
  • Using `urllib.request.urlopen` and manually chunking when `urlretrieve` already handles the progress callback.
  • Not checking if the URL returns a content-length header, leading to unknown total size display.

Variations

  1. Use `tqdm` library for a more modern and animated progress bar with `requests`.
  2. Use `aiohttp` with `asyncio` for asynchronous downloads with progress.

Real-world use cases

  • Downloading large dataset files from a public repository with visual feedback in a CLI tool.
  • Fetching firmware updates or asset bundles in a deployment script while showing progress.
  • Downloading machine learning model weights from a remote URL inside a training pipeline.

Sponsored

Sponsored Reserved space — layout preview until AdSense is connected

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Files & data

Related tutorials and quizzes for this topic.