HTTP Range Requests Explained: Resumable and Partial Downloads
Understand HTTP Range requests and 206 Partial Content. Learn how browsers, download managers, and video players use range requests — with a full Node.js implementation.
HTTP Range Requests (RFC 7233) allow clients to download specific byte ranges of a resource. This is the underlying technology powering video seek bars, multi-threaded download managers (IDM, aria2), and resumable downloads.
The HTTP 206 Partial Content Lifecycle
- Client probe: Client makes a
HEADrequest. The server replies withAccept-Ranges: bytes. - Range request: Client sends
Range: bytes=0-1048575(requesting the first 1MB). - Partial response: Server returns HTTP 206 Partial Content with:
Content-Range: bytes 0-1048575/10485760Content-Length: 1048576
Test HTTP byte range requests with curl against our 10MB PDF sample.
Download 10MB PDF Sample →Testing Byte Ranges with cURL
# Request only the first 500 bytes (to inspect file magic headers)
curl -r 0-499 -i https://filedummy.dev/api/download?type=pdf&size=10mb
Implementing Range Requests in Node.js
import fs from 'fs';
import { IncomingMessage, ServerResponse } from 'http';
export function handleRangeRequest(req: IncomingMessage, res: ServerResponse, filePath: string) {
const stat = fs.statSync(filePath);
const total = stat.size;
const range = req.headers.range;
if (!range) {
res.writeHead(200, {
'Content-Length': total,
'Content-Type': 'application/pdf',
'Accept-Ranges': 'bytes',
});
fs.createReadStream(filePath).pipe(res);
return;
}
const parts = range.replace(/bytes=/, '').split('-');
const start = parseInt(parts[0], 10);
const end = parts[1] ? parseInt(parts[1], 10) : total - 1;
const chunksize = end - start + 1;
res.writeHead(206, {
'Content-Range': `bytes ${start}-${end}/${total}`,
'Accept-Ranges': 'bytes',
'Content-Length': chunksize,
'Content-Type': 'application/pdf',
});
const stream = fs.createReadStream(filePath, { start, end });
stream.pipe(res);
}
Nguyen Dai Long
AuthorBackend Lead • Distributed Systems & Cloud Edge Architecture Specialist
4+ years designing high-throughput file ingestion pipelines, database architectures, and distributed edge storage on Cloudflare R2 & AWS S3. Founder of FileDummy and the NDL Ecosystem.
Was this article helpful?
Click Like to support the author and help other developers discover this guide.
Engineering Discussion & Feedback (0)
Share benchmark results, report edge cases, or ask technical questions.
No comments yet. Be the first developer to start the discussion!
Frequently Asked Questions
What is the HTTP Range request header?▾
The Range header asks the server to return only a specific byte range. Format: Range: bytes=start-end (e.g., bytes=0-1023 for the first 1024 bytes). The server responds with 206 Partial Content and the Content-Range header indicating the returned bytes.
How does video streaming use HTTP Range requests?▾
HTML5 video elements use range requests to seek without downloading the entire video. When you drag the seek bar, the browser sends a Range request for the bytes at that timestamp — this is why you can seek before a video is fully buffered.
How do I check if a server supports range requests?▾
Look for Accept-Ranges: bytes in the HEAD response. Run curl -I https://example.com/file.pdf and check for the header. All major cloud storage services (S3, R2, CloudFront) support ranges natively.