HTTP status code · Client errors (4xx)
416 Range Not Satisfiable
416 Range Not Satisfiable means the client asked for a part of a file, with a Range header, that does not exist, typically starting past the end. The classic case is resuming a download that was already complete, or of a file that changed on the server.
| Class | 4xx, Client errors |
|---|---|
| Also known as | Requested Range Not Satisfiable |
| Defined in | RFC 9110 §15.5.17 |
| Cacheable by default | Only with explicit Cache-Control or Expires |
| Safe to retry | Yes, with a range inside the length given in Content-Range, or without Range |
| Relevant headers |
|
What 416 means
RFC 9110, section 15.5.17, gives two reasons: none of the requested ranges can be satisfied, or the client asked for an excessive number of small or overlapping ranges, which the spec flags as a possible denial of service. A server answering a byte-range request with 416 should send Content-Range with an asterisk and the current length, as in Content-Range: bytes */47022, so the client learns the real size.
Servers may also ignore Range and send the whole file with 200, and many do. You rarely write 416 by hand: Go http.ServeContent and http.ServeFile, Express res.sendFile and express.static, nginx and S3 all generate it when the range is out of bounds. S3 labels it InvalidRange.
Common causes
If you are visiting the site
- A download manager or browser tried to resume a file that had already finished downloading.
- The file on the server was replaced by a smaller version after your partial download started.
If you run the server
- curl -C - or wget -c resumes against a local file that is as large as, or larger than, the remote one.
- A video player seeks using a byte offset computed from stale metadata, after the media file was re-encoded.
- A client sends a Range request for a zero-byte file; no byte range can be satisfied when the representation is empty.
- A CDN caches a shorter object than the origin now holds, so ranges near the end fail at the edge.
How to fix it
If you are visiting the site
- Delete the partial file and download it again from the start.
- Reload the page with the video or file so the player fetches fresh metadata.
If you run the server
- Read the length from Content-Range: bytes */LENGTH in the 416 and compare it with the local partial file; if they match, the download is already complete.
- Send If-Range with the ETag when resuming, so the server returns the full new file with 200 if it changed instead of a 416 or a corrupted mix.
- Purge the CDN object after replacing a file with a different size.
How to send 416
You rarely need this by hand. Go http.ServeContent and http.ServeFile, Express res.sendFile and express.static, and nginx static serving answer 416 with the right Content-Range automatically.
app.get('/files/:name', (req, res) => {
res.set('Content-Range', 'bytes */47022');
res.status(416).end();
});// app/files/[name]/route.ts
export async function GET() {
return new Response(
null,
{ status: 416, headers: { 'Content-Range': 'bytes */47022' } }
);
}mux.HandleFunc("GET /files/{name}", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Range", "bytes */47022")
w.WriteHeader(http.StatusRequestedRangeNotSatisfiable) // 416
})from fastapi import FastAPI, Response
app = FastAPI()
@app.get("/files/{name}")
def get_file(name: str):
return Response(status_code=416, headers={"Content-Range": "bytes */47022"})# Ask for bytes past the end of a 47022-byte file
curl -sI -H 'Range: bytes=50000-' https://example.com/files/report.pdf
# HTTP/2 416
# content-range: bytes */47022Commonly confused with
- 416 vs 206
- 206 Partial Content is the success answer to a Range request; 416 is the failure when the range is impossible.
- 416 vs 200
- A server that ignores Range sends 200 with the full file, which is also allowed and avoids 416 entirely.
Frequently asked questions
- Why does curl -C - return 416?
- curl asks for bytes starting at the size of your local file. If that file is already complete, the start offset equals the remote size and no bytes remain, so the server answers 416. The download is usually done.
- What should a 416 response contain?
- RFC 9110 says a server answering a byte-range request with 416 should include Content-Range: bytes */LENGTH with the current size of the resource.
- Can a server ignore the Range header instead?
- Yes. Range support is optional, and many servers answer an unsatisfiable or unsupported range with 200 and the full body. Clients have to handle both.
Last reviewed by Arielton Oberek.