HTTP range requests

Don’t re-download the whole file — ask the server for just the bytes you’re missing.

The idea

A normal GET hands you the whole file with 200 OK. But if the file is large and your connection drops halfway, you don’t want to start over. HTTP/1.1 byte-range requests (RFC 7233) let the client say Range: bytes=400-999, and the server replies 206 Partial Content with only those bytes plus a Content-Range header naming exactly which slice you got.

Ranges are zero-indexed and inclusive on both ends, so bytes=0-99 is the first 100 bytes. This one mechanism powers resumable downloads, video seeking, and parallel chunked downloads.

GET /movie.mp4 awaiting… byte 0 byte 999
A 1,000-byte file, drawn as 20 cells of 50 bytes each. Press play to watch a download stall, then resume with a range request.

How it works

The client advertises nothing special on the first try — a plain GET. The server replies 200 OK and includes Accept-Ranges: bytes to advertise that ranges are supported. After the transfer dies at byte 400, the client re-requests starting where it left off. The server answers 206 with a Content-Range that pins the exact slice and total size.

--- attempt 2: resume after stalling at byte 400 ---
GET /movie.mp4 HTTP/1.1
Host: example.com
Range: bytes=400-999

HTTP/1.1 206 Partial Content
Accept-Ranges: bytes
Content-Range: bytes 400-999/1000
Content-Length: 600

<bytes 400 through 999, inclusive>

The client appends those 600 bytes to the 400 it already holds and the file is whole. Content-Range: bytes 400-999/1000 reads as “here are bytes 400 through 999 of a 1000-byte file.”

Cost

Only the requested bytes cross the wire — nothing already received is re-sent. That single property unlocks three big wins.

UseHow range helps
ResumeRe-request from the first missing byte; the rest stays put.
Seek / streamJump to a video timestamp by fetching only that region.
ParallelSplit a file into chunks, fetch each with its own range, stitch.
CountingBytes returned = end - start + 1 (inclusive), so 400-999 is 600.

Watch out for

Worked example

You’re downloading a 1,000-byte file and the connection dies after byte 400 lands. You already hold bytes 0..399 (that’s 400 bytes). The next byte you need is byte 400, and the last byte is 999 (a 1,000-byte file is indexed 0..999).

resume range   = bytes=400-999
status         = 206 Partial Content
Content-Range  = bytes 400-999/1000
bytes returned = 999 - 400 + 1 = 600

400 already on disk + 600 just fetched = 1,000. Done, without re-sending a single byte you already had. Now picture bytes=2000-3000 instead: 2000 is past the end, so the server replies 416 and sends no bytes at all.

Check yourself

How many bytes does Range: bytes=0-99 return from a large file?

Which status code means “the server gave you only part of the file”?