Skip to main content
416

Range Not Satisfiable

Active
RFC 9110 §15.5.17Since 1999Video streaming, resumable downloads, PDF viewers, CDNs, range-based APIs

HTTP 416 Range Not Satisfiable indicates the requested ranges cannot be satisfied for the selected resource. Defined in RFC 9110 §15.5.17. The server SHOULD respond with Content-Range indicating resource length. Common in video streaming and resumable downloads.

Description

The 416 Range Not Satisfiable status code indicates that the set of ranges in the request's Range header field has been examined and none of the requested ranges are satisfiable. The ranges are either beyond the current extent of the selected resource or the set of ranges requested has been rejected due to invalid ranges or an excessive number of small ranges.

When a server returns 416, it SHOULD generate a Content-Range header field specifying the current length of the selected representation. For byte ranges, this takes the form `Content-Range: bytes */12345` where 12345 is the total size. This gives the client the information needed to construct a valid range request on retry.

It is critical to distinguish between syntactically invalid Range headers and unsatisfiable ones. If the Range header is syntactically invalid (e.g., `Range: bytes=abc-xyz` or completely malformed), the server should ignore the Range header entirely and return 200 with the full resource — NOT 416. The 416 response is reserved specifically for ranges that are syntactically valid but cannot be fulfilled given the resource's actual size.

This status code is central to the partial content delivery ecosystem. Video players seeking beyond buffered content, download managers resuming past the end of a file, PDF viewers requesting pages beyond the document's extent — all trigger 416. The response acts as a corrective signal, telling the client the actual boundaries of the resource so it can adjust its next request accordingly.

Examples

Requesting bytes beyond end of file
http
GET /videos/intro.mp4 HTTP/1.1
Host: cdn.example.com
Range: bytes=50000-60000
416 response — range exceeds resource length
http
HTTP/1.1 416 Range Not Satisfiable
Content-Range: bytes */12000
Content-Type: application/json

{"error": "range_not_satisfiable", "message": "Requested range bytes=50000-60000 exceeds resource length of 12000 bytes.", "resource_length": 12000}
Resumable download — stale offset after file changed
http
GET /releases/app-v2.3.tar.gz HTTP/1.1
Host: downloads.example.com
Range: bytes=8388608-
If-Range: "v2.2-etag-abc"
416 response — resource was replaced, old range invalid
http
HTTP/1.1 416 Range Not Satisfiable
Content-Range: bytes */5242880
ETag: "v2.3-etag-def"
Content-Type: application/json

{"error": "range_not_satisfiable", "message": "Resource has changed. New length is 5242880 bytes. Your requested offset 8388608 exceeds current size.", "current_etag": "v2.3-etag-def", "resource_length": 5242880}
Multiple ranges — all unsatisfiable
http
GET /documents/report.pdf HTTP/1.1
Host: docs.example.com
Range: bytes=100000-110000, 200000-210000
416 response — multipart range failure
http
HTTP/1.1 416 Range Not Satisfiable
Content-Range: bytes */45000
Content-Type: application/json

{"error": "range_not_satisfiable", "message": "None of the requested ranges (100000-110000, 200000-210000) can be satisfied. Resource length is 45000 bytes.", "resource_length": 45000, "requested_ranges": ["100000-110000", "200000-210000"]}

Edge Cases

  • A syntactically INVALID Range header (e.g., `Range: bytes=abc-xyz`) should NOT trigger 416 — the server must ignore it and return 200 with full content. 416 is only for valid syntax with unsatisfiable values.
  • If the resource has zero bytes (empty file), ANY byte range request triggers 416 because no byte positions exist. The response should be `Content-Range: bytes */0`.
  • A suffix range like `Range: bytes=-0` requests zero bytes from the end — this is technically valid syntax but unsatisfiable (no bytes selected), triggering 416 on most servers.
  • When a resource changes between a HEAD (to get length) and a subsequent GET with Range, the client's range may become invalid. Use If-Range with ETag or Last-Modified to detect this race condition — the server returns 200 with full content instead of 416.
  • CDNs may cache 416 responses. If the origin resource grows (e.g., live stream, appending log), stale cached 416 responses will incorrectly reject valid ranges. Set `Cache-Control: no-store` on 416 responses for dynamic resources.
  • Some servers return 416 for excessively fragmented multipart ranges (e.g., 1000 tiny ranges) as a denial-of-service mitigation, even if each individual range is technically within bounds.
  • Video players seeking near the end of a file may request a range that starts within bounds but extends beyond it (e.g., `Range: bytes=11000-15000` on a 12000-byte file). RFC 9110 says this is satisfiable — the server returns 206 with bytes 11000-11999. Only when the START position exceeds length does 416 apply.

When You'll See This

  • Video player seeks to a timestamp beyond the file's duration (byte offset exceeds file length)
  • Download manager resumes a download but the file was replaced with a smaller version on the server
  • PDF viewer requests a page range that maps to byte offsets beyond the document's actual size
  • Client cached the Content-Length from a previous response but the resource has since been truncated
  • Automated backup tool requests a range based on stale metadata after the source file was compacted
  • Browser's media element requests the final chunk of an audio file but miscalculates the offset
  • API client performing paginated binary export requests a byte offset beyond the export's total output

Implementation References

LanguageConstant
Gohttp.StatusRequestedRangeNotSatisfiable
Rusthttp::StatusCode::RANGE_NOT_SATISFIABLE
Pythonhttp.HTTPStatus.REQUESTED_RANGE_NOT_SATISFIABLE
Node.jshttp.STATUS_CODES[416]
.NETHttpStatusCode.RequestedRangeNotSatisfiable
JavaHttpURLConnection.HTTP_REQ_TOO_LONG (non-standard); use 416 literal
PHPResponse::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE (Symfony)
Ruby:range_not_satisfiable (Rack)

History

Introduced as '416 Requested Range Not Satisfiable' in HTTP/1.1 (RFC 2616, 1999) alongside the Range/Content-Range mechanism for partial content delivery. Renamed to '416 Range Not Satisfiable' in RFC 7233 (2014) for brevity. Carried forward unchanged in RFC 9110 (2022) §15.5.17 as part of the consolidated HTTP semantics specification.

Related Status Codes

Related Headers

FAQ

When should a server return 416 vs ignoring the Range header and returning 200?

Return 416 only when the Range header is syntactically valid but the requested byte positions are beyond the resource's extent (e.g., start position >= content length). If the Range header is syntactically malformed (invalid format, non-numeric values), the server MUST ignore it per RFC 9110 and serve the full resource with 200. The key test: can you parse it into actual numeric ranges? If yes but they exceed the file, 416. If no, ignore and serve 200.

What should the Content-Range header contain in a 416 response?

The Content-Range header in a 416 response uses the unsatisfied-range format: `Content-Range: bytes */[total-length]`. For example, `Content-Range: bytes */12345` tells the client the resource is 12345 bytes long. This is essential — it gives the client the exact information needed to construct a valid range request on retry. If the length is unknown (e.g., dynamically generated content), use `Content-Range: bytes */*`.

How do resumable downloads handle 416 gracefully?

A well-implemented download client: (1) stores the ETag or Last-Modified from the original response, (2) on resume, sends both Range and If-Range headers, (3) if the server returns 416, reads the Content-Range header to learn the new file size, (4) if the new size is smaller than the downloaded portion, discards and restarts, (5) if the ETag changed (different file), restarts from zero. The If-Range pattern avoids 416 entirely when the resource changed — the server returns 200 with full content instead.