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

Checklist (most common first)

  1. Server ignores Range — response is 200 with the full body despite a Range header. Confirm with curl (below). Fix origin/CDN config; for nginx, ensure proxy_force_ranges on; when proxying, and that the upstream supports ranges.
  2. 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.
  3. 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.
  4. 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.
  5. Size or ETag changed — publisher replaced the file. Local partial no longer matches; starting over is correct. Compare ETag / Last-Modified / total size in Content-Range.
  6. Auth / cookies expired — second request returns 401/403; the client falls back to a fresh full download after re-login.
  7. Middlebox buffered the whole response — corporate proxies sometimes flatten 206 into 200. Try another network or HTTPS end-to-end.
  8. 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

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 .

Try it

Related guides

Newest guides