Resume a download with Range

Resume an interrupted download by requesting only the bytes after what you already have, using the `Range` header and 206 Partial Content.

Overview

Resume an interrupted download by requesting only the bytes after what you already have, using the `Range` header and 206 Partial Content.

In code

# resume a partially downloaded file automatically:
curl -C - -O https://example.com/big.iso

# or request an explicit byte range:
curl -r 1048576- -o part.bin https://example.com/big.iso
#   -> 206 Partial Content
// fetch bytes starting at an offset (e.g. after 1 MiB already saved)
const res = await fetch('https://example.com/big.iso', {
  headers: { Range: 'bytes=1048576-' }
});
console.log(res.status); // 206 Partial Content
console.log(res.headers.get('Content-Range')); // bytes 1048576-.../<total>
import os, requests

path, url = 'big.iso', 'https://example.com/big.iso'
have = os.path.getsize(path) if os.path.exists(path) else 0
headers = {'Range': f'bytes={have}-'}

with requests.get(url, headers=headers, stream=True) as r:
    r.raise_for_status()  # 206 if resumed, 200 if server ignores Range
    with open(path, 'ab') as f:  # append mode
        for chunk in r.iter_content(8192):
            f.write(chunk)

Details

curl's `-C -` inspects the local file size and computes the resume offset automatically. To specify it yourself use `-r start-end` (e.g. `-r 1048576-`) or `Range: bytes=<start>-`. If the server supports partial requests it returns 206 with a `Content-Range: bytes start-end/total` header.

Check whether the server supports ranges via `Accept-Ranges: bytes` in the response. If it does not, it ignores Range and sends 200 with the whole file, so your client must branch: on a 200, save from scratch (overwrite, not append).

If the source changes mid-resume, the pieces won't line up and the file corrupts. Prevent this with `If-Range: "<etag>"`: unchanged resources continue with 206, changed ones are re-sent in full with 200, preserving integrity. A range beyond the file size yields 416 Range Not Satisfiable.

Related headers

Related status codes