Skip to content
Webmaster Tools

206 Partial Content

What HTTP 206 Partial Content means, how Range, Content-Range, Accept-Ranges and If-Range work, and how to fix servers that ignore or break range requests.

All status codes

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.
  • Accept-Ranges: bytes advertises support; Accept-Ranges: none says don't bother.
  • A server may ignore Range and 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-Range with the ETag (or Last-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 on aren't range-able; serve media uncompressed (it's already compressed). When proxying, upstreams must handle Range themselves, or set proxy_force_ranges on for cached responses.
  • Apache handles ranges for static files; check that a filter like mod_deflate isn't applied to media types.
  • Node/Express: express.static and res.sendFile support ranges and If-Range. If you stream files yourself with fs.createReadStream, parse Range, pass start and end, and set Content-Range and 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 Range to 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.

Send a request with your own Range header and inspect Content-Range in the HTTP Request Builder.