Accept-Ranges transfer response
Tells the client whether the server supports range requests for this resource.
What it does
Accept-Ranges tells the client whether the server supports range requests for the requested resource — and if so, what unit system it uses. A client that sees Accept-Ranges: bytes knows it can safely send a Range header on subsequent requests for partial content.
It's the server's advertisement of range request capability.
Syntax
Accept-Ranges: bytes
Accept-Ranges: none
Only two values matter in practice:
| Value | Meaning |
|---|---|
bytes |
Server supports byte-range requests. Client can send Range: bytes=... |
none |
Server does not support range requests. Client should not attempt Range |
Where it appears
Accept-Ranges typically appears on:
HEAD responses — a client can probe for range support without downloading the resource:
HEAD /videos/tutorial.mp4 HTTP/1.1
HTTP/1.1 200 OK
Content-Length: 94371840
Accept-Ranges: bytes
ETag: "abc123"
GET responses — the server advertises support on the initial full download:
HTTP/1.1 200 OK
Content-Type: video/mp4
Content-Length: 94371840
Accept-Ranges: bytes
206 Partial Content responses — confirming range support on partial responses (redundant but common).
Accept-Ranges: none
When a server explicitly doesn't support range requests:
HTTP/1.1 200 OK
Accept-Ranges: none
This tells download managers, media players, and HTTP clients not to bother attempting range requests. Without this, they'd have to find out by sending a Range request and receiving a 200 (full content) instead of the expected 206.
Absence vs none
The absence of Accept-Ranges doesn't mean range requests aren't supported — it just means the server hasn't declared its support. Many servers that support ranges omit Accept-Ranges on some responses. A client can still attempt a range request; it just won't know in advance whether it'll work.
Accept-Ranges: none is an explicit "don't bother" signal. Its presence is more informative than its absence.
The full range request trio
Accept-Ranges, Range, and Content-Range work together:
- Server → client:
Accept-Ranges: bytes(I support ranges) - Client → server:
Range: bytes=0-1023(give me the first 1KB) - Server → client:
Content-Range: bytes 0-1023/94371840(here it is, full size is 94MB)
Common mistakes and gotchas
Not setting Accept-Ranges on static file servers. nginx and Apache set it automatically for static files. But if you're serving files through application code, you need to set it manually if you implement range support.
Setting Accept-Ranges: bytes without actually implementing ranges. If you declare support but then return 200 OK with the full resource on range requests, download managers will be confused — they expect 206 and may mishandle the 200.
Real-world example
HEAD probe before resuming download:
HEAD /downloads/ubuntu-22.04.iso HTTP/1.1
Host: releases.ubuntu.com
HTTP/1.1 200 OK
Content-Length: 1466714112
Accept-Ranges: bytes
ETag: "d41d8cd98f00"
Last-Modified: Thu, 01 Jan 2026 00:00:00 GMT
Client sees Accept-Ranges: bytes and Content-Length, knows it can resume the download with Range: bytes=<already-downloaded>-.
FAQ
Does Accept-Ranges: bytes mean the server supports all range formats?
bytes is the only range unit in widespread use. The spec allows custom units but none exist in practice. Accept-Ranges: bytes effectively means "range requests are supported."
Is Accept-Ranges sent by CDNs?
Yes — CDNs like Cloudflare, Fastly, and CloudFront set Accept-Ranges: bytes for assets they serve. This is how browsers can seek in videos served from CDNs.
Fun fact
Accept-Ranges: none is one of HTTP's rare explicit-negative signals — most HTTP headers simply omit information when it doesn't apply rather than declaring its absence. The designers included none specifically because download managers and media players were sending range requests speculatively (without knowing if ranges were supported) and wasting round trips finding out. An explicit none saves that wasted probe request.