HTTP 206 Partial Content and Accept-Ranges
A download died halfway. The client asks for only the missing bytes. When the server agrees, the status is 206 Partial Content — not another full 200.
What you see
HTTP/1.1 206 Partial Content
Accept-Ranges: bytes
Content-Range: bytes 1048576-2097151/5242880
Content-Length: 1048576
Content-Type: application/octet-stream
Compare with a normal file fetch: 200 OK + full Content-Length and no Content-Range. Status 206 is success for a ranged request; it is not an error.
The handshake in three headers
Accept-Ranges: bytes— server advertises that Range is allowed (often on ordinary 200 responses too). Some servers omit it but still honour Range; others advertise it and still refuse later.Range: bytes=1000-1999(request) — client wants that inclusive slice. Open endbytes=1000-means “from 1000 to EOF”. Suffixbytes=-500means “last 500 bytes”.Content-Range: bytes 1000-1999/5000(response) — which slice was returned and the total size (or*if unknown).
Quick proof with curl
# Ask for the first kilobyte of a file
curl -i -H 'Range: bytes=0-1023' https://example.com/big.bin
# Expect 206 + Content-Range. A 200 with the whole file means ranges are ignored.
# A 416 means the range was invalid for that resource (see the 416 guide).
Why resume saves time
If you already have the first 40 MB of a 100 MB installer, a ranged GET for bytes=41943040- re-downloads only the remaining 60 MB. The “restart from zero” path wastes the bytes you already paid for in time and bandwidth — same idea as the numbered-piece board on learn.oddlathe.com/resume.
| Status | Meaning for downloads |
|---|---|
| 200 | Whole representation (range ignored or not requested) |
| 206 | Only the requested byte range |
| 416 | Range not satisfiable — fix offsets or re-fetch from zero |
| 301/302/307/308 | Redirect; the final URL must still support ranges |
Multipart ranges
A client can ask for several slices at once (Range: bytes=0-99,200-299). Servers may reply with multipart/byteranges. Most download managers stick to a single contiguous range; browsers usually do too for media seeking.
Not the same as
- 301/302/307/308 redirects — location changed; ranged support is a property of the target.
- 502 Bad Gateway / ETIMEDOUT / ECONNRESET — the transfer died; resume is how you recover after reconnecting.
- Streaming video “adaptive bitrate” — different URLs or segments (HLS/DASH), not necessarily one file’s byte ranges (though MP4 progressive download often uses Range for seeking).
Related
Accept-Ranges header · Content-Range header · Range returns 200, not 206 · Download won't resume / starts over · HTTP 416 Range Not Satisfiable · ETIMEDOUT · ECONNRESET · 401 vs 403 · Wirebook: resume downloads · Anvil HTTP status
Questions
What does HTTP 206 Partial Content mean?
The server successfully returned only part of the resource, matching a Range request. It is a success status, not an error.
What is Accept-Ranges: bytes?
An advertisement that the server understands byte-range requests. Clients use it (plus trial Range requests) to decide whether resume/seek is possible.
Is Content-Length the full file size on a 206?
No. On 206, Content-Length is the size of the partial body. The full size is in Content-Range after the slash.
Can I resume across redirects?
Only if the final URL supports ranges and your client re-issues Range against that URL with a stable ETag/size. See the won't-resume guide.
Do CDNs support 206?
Most do for cacheable static objects. Dynamic or auth-gated URLs may strip Range or always return 200.
How is this different from chunked Transfer-Encoding?
Chunked encoding streams an unknown-length body in pieces for one response. 206 is a separate status for a client-chosen byte window of a known resource.
Published · updated .