Download won't resume / always starts over
You click Resume and the progress bar snaps back to 0%. The client asked for the rest of the file; the server (or something in front of it) handed back the whole thing — or refused ranges entirely.
Symptoms
- Browser “Resume” restarts at 0% or creates
file (1).bin. curl -C -/wget -cre-downloads everything or errors out.- Package managers re-fetch a huge layer after a Wi-Fi blip.
Checklist (most common first)
- Server ignores Range — response is
200with the full body despite a Range header. Confirm with curl (below). Fix origin/CDN config; for nginx, ensureproxy_force_ranges on;when proxying, and that the upstream supports ranges. Accept-Ranges: none— explicit refusal (common on some app servers and gzip-on-the-fly responses). Serve the file as a static object, or disable transforming compression for that path so byte offsets stay meaningful.- URL changed between attempts — pre-signed S3/GCS URLs, rotating CDN tokens, or “latest” redirects. Save the final URL from the first attempt; resume against that exact URL before it expires.
- Redirect chain drops Range — some clients re-GET without Range after 302. Prefer 307/308 for method/body preservation, or resolve redirects once and resume on the final host. Related: 301 vs 302 vs 307 vs 308.
- Size or ETag changed — publisher replaced the file. Local partial no longer matches; starting over is correct. Compare
ETag/Last-Modified/ total size inContent-Range. - Auth / cookies expired — second request returns 401/403; the client falls back to a fresh full download after re-login.
- Middlebox buffered the whole response — corporate proxies sometimes flatten 206 into 200. Try another network or HTTPS end-to-end.
- Client never asked — some “download” buttons use fetch/XHR without Range, or open a new navigation. Use a manager that supports continue, or
curl -C - -O URL.
Prove it in 30 seconds
# 1) Does the server advertise ranges?
curl -sI https://example.com/file.bin | grep -i accept-ranges
# 2) Does it honour a Range?
curl -sI -H 'Range: bytes=0-0' https://example.com/file.bin
# Good: HTTP/1.1 206 … Content-Range: bytes 0-0/TOTAL
# Bad: HTTP/1.1 200 … (full file) or Accept-Ranges: none
# 3) Resume from a local partial (curl writes the rest)
curl -C - -o file.bin https://example.com/file.bin
Gzip and “identity” encoding
If the server gzips on the fly, byte 1 000 000 of the compressed stream is not byte 1 000 000 of the file. Many stacks disable ranges when using dynamic gzip, or only range the uncompressed object. Prefer storing precompressed .gz as a separate URL if you need both compression and resume.
When starting over is the right move
- The remote object changed (checksum / ETag mismatch).
- You only have a corrupt partial and no checksum to validate prefixes.
- The server returns 416 because your local size is past EOF.
Related
Resume with curl or wget · Range returns 200, not 206 · Accept-Ranges header · HTTP 206 Partial Content · HTTP 416 Range Not Satisfiable · ETIMEDOUT · ECONNRESET · Too many redirects · Wirebook: numbered pieces / resume
Questions
Why does my download always start over?
Usually the server ignores Range (returns 200), the URL expired or changed, or a redirect/proxy stripped partial content. Verify with curl -H 'Range: bytes=0-0'.
Accept-Ranges says bytes but resume still fails
Advertisement can lie, or only some paths support it. Test an actual Range request; check redirects and ETag stability.
Does wget -c need server support?
Yes. -c sends a Range from the local file size. Without 206, wget may re-get the whole file or abort depending on version/flags.
Browser created 'file (1).bin' instead of resuming
It treated the response as a new download (often a 200). Clear the partial, fix server ranges, or use a download manager that merges by ETag.
Can I resume after ETIMEDOUT / ECONNRESET?
Yes — that is the point of ranges. Reconnect and request bytes from your local length, if the server still supports 206 on the same object.
Is HTML5 video seeking the same bug?
Seeking often uses Range on one media file. If seek always rebuffers from 0, the media URL may not support 206 — same checklist.
Published · updated .