What 206 means
The server is sending only part of the resource: the byte ranges the client asked for in its Range header. 206 is defined in RFC 9110 §15.3.7, and range requests in §14. A client asks for bytes 0 to 1023 of a file:
GET /video.mp4 HTTP/1.1
Host: example.com
Range: bytes=0-1023
and the server answers with just those bytes and a Content-Range saying where they sit in the whole:
HTTP/1.1 206 Partial Content
Content-Range: bytes 0-1023/48213904
Content-Length: 1024
Content-Type: video/mp4
Accept-Ranges: bytes
ETag: "5f3a-2dfb8d0"
Ranges are inclusive and zero-based. bytes=500- means from byte 500 to the end, and bytes=-500 means the last 500 bytes. A request for several ranges (bytes=0-99,200-299) gets one multipart/byteranges body with each part labelled by its own Content-Range.
Where you see it
- Video and audio players seeking to a position, and browsers loading media progressively.
- Resumable downloads: download managers,
curl -C -, package managers and OS updaters. - PDF viewers that fetch only the pages being displayed.
- Parallel download tools that fetch several ranges at once.
Related rules
Accept-Ranges: bytesadvertises support;Accept-Ranges: nonesays don't bother.- A server may ignore
Rangeand send a normal 200 with the full body. Clients must handle that. - A range that starts beyond the end of the file gets 416 Range Not Satisfiable, with
Content-Range: bytes */48213904. - To resume safely, a client sends
If-Rangewith theETag(orLast-Modified) it saw before. If the file changed, the server sends the whole new file as 200 instead of a mismatched piece. - 206 is cacheable by default, and caches may combine stored ranges of the same representation.
How to fix broken range support
- nginx serves ranges for static files out of the box. Responses compressed on the fly with
gzip onaren't range-able; serve media uncompressed (it's already compressed). When proxying, upstreams must handleRangethemselves, or setproxy_force_ranges onfor cached responses. - Apache handles ranges for static files; check that a filter like mod_deflate isn't applied to media types.
- Node/Express:
express.staticandres.sendFilesupport ranges andIf-Range. If you stream files yourself withfs.createReadStream, parseRange, passstartandend, and setContent-Rangeand 206. - Videos that won't seek (especially in Safari, which requires range support for video) usually mean the server answers 200 to range requests or omits
Content-Length. - CDNs: check that the CDN caches and serves byte ranges for large files, or that it forwards
Rangeto the origin.
206 and SEO
206 doesn't affect the indexing of web pages: crawlers fetch HTML in full and get 200. For media files, make sure range requests work so that browsers, and any service that previews or processes your video, can read them. Never return 206 to a request that had no Range header.
Related codes
- 200 OK: the full resource, also the valid answer when a server ignores
Range. - 304 Not Modified: the other conditional,
ETag-driven response. - 416 Range Not Satisfiable: the requested range is outside the file.
Send a request with your own Range header and inspect Content-Range in the HTTP Request Builder.