HTTP Fundamentals

HTTP Range Requests and Partial Content

How HTTP range requests enable resumable downloads and video streaming using the Range header, 206 Partial Content, and multipart responses.

What Are Range Requests?

Range requests allow a client to request only a portion of a resource instead of the whole thing. This is the mechanism behind:

  • Resumable downloads — resume after a dropped connection
  • Video streaming — seek to any point in a video without re-downloading from the start
  • Parallel downloads — download different parts of a large file simultaneously

Range Header Syntax

The Range header uses byte ranges (zero-indexed):

Range: bytes=0-1023        # First 1,024 bytes
Range: bytes=500-999       # Bytes 500 through 999 (inclusive)
Range: bytes=-500          # Last 500 bytes
Range: bytes=9500-         # From byte 9,500 to end of file

Before making a range request, clients often send a HEAD request to check if the server supports ranges:

curl -I https://example.com/large-file.zip
# Look for: Accept-Ranges: bytes

If the server responds with Accept-Ranges: none, it does not support range requests.

206 Partial Content

When a valid range request is honored, the server returns 206 Partial Content with Content-Range telling the client what slice it received:

HTTP/1.1 206 Partial Content
Content-Range: bytes 0-1023/146515
Content-Length: 1024
Accept-Ranges: bytes
Content-Type: application/zip

The Content-Range format is bytes <start>-<end>/<total>. If the total is unknown, * is used instead.

Multipart Range Responses

A client can request multiple non-contiguous ranges in a single request:

Range: bytes=0-50, 100-150

The server responds with a multipart body:

HTTP/1.1 206 Partial Content
Content-Type: multipart/byteranges; boundary=BOUNDARY

--BOUNDARY
Content-Type: application/zip
Content-Range: bytes 0-50/146515
<bytes 0-50>
--BOUNDARY
Content-Type: application/zip
Content-Range: bytes 100-150/146515
<bytes 100-150>
--BOUNDARY--

Multipart ranges are rarely used in practice — the overhead of multiple requests is usually lower than parsing a multipart body.

Resumable Downloads

Here is how a client implements a resumable download:

import os
import requests

def download_resumable(url: str, dest: str) -> None:
    existing_size = os.path.getsize(dest) if os.path.exists(dest) else 0
    headers = {}
    if existing_size > 0:
        headers['Range'] = f'bytes={existing_size}-'
    response = requests.get(url, headers=headers, stream=True)
    mode = 'ab' if response.status_code == 206 else 'wb'
    with open(dest, mode) as f:
        for chunk in response.iter_content(chunk_size=65536):
            f.write(chunk)

Video Streaming

Browsers use range requests extensively for <video> elements. When a user seeks to a timestamp, the browser sends a range request for the byte offset corresponding to that timestamp:

Range: bytes=4194304-

This is why you must serve video files from a server that supports Accept-Ranges: bytes. Static file servers (nginx, S3, CDNs) handle this automatically.

nginx configuration for range support:

location /videos/ {
    root /var/www/media;
    # nginx supports range requests by default for static files
}

416 Range Not Satisfiable

When the requested range is invalid (e.g., start > total size), the server returns 416 Range Not Satisfiable:

HTTP/1.1 416 Range Not Satisfiable
Content-Range: bytes */146515

The */<total> format in Content-Range tells the client the actual file size so it can adjust its request.

Conditional Range Requests

To avoid downloading the wrong data if the file changed between requests, combine Range with If-Range:

Range: bytes=500-999
If-Range: "abc123etag"

If the ETag still matches, the server returns 206 with the range. If the resource changed, it returns 200 with the full resource instead of the range — preventing corrupted partial content.

Summary

Range requests are essential infrastructure for video streaming and large file downloads. Key points:

  • Check Accept-Ranges: bytes before attempting a range request
  • A successful range response uses 206 Partial Content
  • Use If-Range with an ETag for safe resumable downloads
  • Handle 416 by re-querying the file size from Content-Range: */N

संबंधित प्रोटोकॉल

संबंधित शब्दावली शब्द

इसमें और HTTP Fundamentals