Skip to main content

14. Range Requests

Clients often encounter interrupted transfers or need to obtain only a subset of a large representation. Range requests are an optional feature that allows clients to request one or more subranges of the selected representation, rather than the entire representation.

The range request mechanism is useful in several different scenarios:

  • Partial downloads of large files can be split into multiple concurrent requests, thereby speeding up overall retrieval
  • Interrupted transfers can be resumed from the point of interruption rather than restarting
  • Some media types allow incremental rendering or playback, and user agents can start processing data as it is received

Servers are not required to support range requests. However, origin servers SHOULD support range requests, since range requests can reduce network usage and improve service responsiveness.

14.1. Range Units

Representations can be partitioned into subranges in different ways. A range unit defines how representation data is partitioned.

range-unit       = token

All range unit names are case-insensitive and SHOULD be registered in the HTTP Range Unit Registry.

14.1.1. Range Specifiers

A range specifier defines one or more subranges of representation data.

range-spec       = range-unit "=" range-set
range-set = 1#range-spec-value
range-spec-value = int-range / suffix-range / other-range

Range units allow clients to state what kind of range they are requesting.

14.1.2. Byte Ranges

The "bytes" range unit is defined for HTTP, representing subranges of an octet sequence (i.e., byte ranges).

byte-ranges-specifier = bytes-unit "=" byte-range-set
byte-range-set = 1#byte-range-spec
byte-range-spec = first-byte-pos "-" [ last-byte-pos ]
/ suffix-byte-range-spec
suffix-byte-range-spec = "-" suffix-length

first-byte-pos = 1*DIGIT
last-byte-pos = 1*DIGIT
suffix-length = 1*DIGIT
bytes-unit = "bytes"

The first-byte-pos value gives the byte-offset of the first byte in the range. The last-byte-pos value gives the byte-offset of the last byte in the range; that is, the byte positions specified are inclusive. Byte offsets start at zero.

Examples:

  • bytes=0-499 represents the first 500 bytes
  • bytes=500-999 represents the second 500 bytes
  • bytes=-500 represents the last 500 bytes
  • bytes=500- represents all bytes from byte 500 onwards
  • bytes=0-0,-1 represents the first and last bytes

14.2. Range

The "Range" header field is used to request one or more subranges of representation data.

Range = range-unit "=" range-set

A server MAY ignore the Range header field. However, origin servers and intermediate caches SHOULD support byte ranges when possible, since Range support enables efficient recovery from partially failed transfers and partial retrieval of large representations.

A server MUST ignore a Range header field received with a request method other than GET.

An origin server that supports the Range header field MUST, if all preconditions are true:

  1. Ignore the Range header field if it contains a range unit it does not support
  2. Return a 416 (Range Not Satisfiable) status code if the Range header field is syntactically invalid
  3. Return a 206 (Partial Content) response containing one or more partial representations if the Range header field contains a satisfiable set of byte ranges

Example request:

GET /document HTTP/1.1
Host: www.example.com
Range: bytes=0-1023

14.3. Accept-Ranges

The "Accept-Ranges" header field allows a server to indicate that it supports range requests for the target resource.

Accept-Ranges = acceptable-ranges
acceptable-ranges = 1#range-unit / "none"

An origin server that accepts range requests for a given target resource SHOULD send an Accept-Ranges header field to indicate what range units are supported. A client MAY generate range requests without receiving this header field.

Examples:

Accept-Ranges: bytes
Accept-Ranges: none

The "none" value indicates that no range units are accepted, meaning the server does not support any range requests for that resource.

14.4. Content-Range

The "Content-Range" header field is sent in a single-part 206 (Partial Content) response to indicate the byte range of the enclosed partial representation, or in a 416 (Range Not Satisfiable) response to provide information about the selected representation.

Content-Range       = range-unit SP
( range-resp / unsatisfied-range )

range-resp = byte-content-range
/ other-range-resp
byte-content-range = bytes-unit SP
( byte-range-resp / unsatisfied-range )

byte-range-resp = first-byte-pos "-" last-byte-pos
"/" ( complete-length / "*" )
complete-length = 1*DIGIT

unsatisfied-range = "*/" complete-length

other-range-resp = *CHAR

Examples:

Content-Range: bytes 0-1023/5000
Content-Range: bytes 1024-2047/5000
Content-Range: bytes */5000

The first example indicates that the first 1024 bytes of a complete representation (with a length of 5000 bytes) are being transferred. The third example indicates that a range request could not be satisfied because the complete length of the selected representation is 5000 bytes.

14.5. Partial PUT

A partial PUT request is not a range request, but it uses the same mechanism as range requests to describe the content being transferred. A client can send a partial PUT by including a Content-Range header field in the PUT request.

However, partial PUT is rarely used in practice because:

  1. It requires the client to know the current state of the resource
  2. It is vulnerable to race conditions
  3. Most origin servers do not support it

Therefore, clients SHOULD NOT use partial PUT unless they are certain the target server supports it.

14.6. Media Type multipart/byteranges

When sending multiple ranges, a server SHOULD use the multipart/byteranges media type.

multipart/byteranges

Each body part of this media type MUST include:

  • A Content-Type header field indicating the media type of the representation contained in that body part
  • A Content-Range header field indicating the range contained

Example response:

HTTP/1.1 206 Partial Content
Content-Type: multipart/byteranges; boundary=THIS_STRING_SEPARATES

--THIS_STRING_SEPARATES
Content-Type: text/html
Content-Range: bytes 0-100/1234

[first 101 bytes]
--THIS_STRING_SEPARATES
Content-Type: text/html
Content-Range: bytes 500-999/1234

[bytes 500-999]
--THIS_STRING_SEPARATES--

When a client requests multiple disjoint ranges, a server SHOULD return a multipart response only if:

  1. The ranges do not overlap
  2. The order of ranges is the same as their order in the representation

Otherwise, the server SHOULD return the entire representation or coalesce overlapping ranges.