FileDummy Logo
FileDummy
Cloud Storage & CDN

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.

October 5, 202611 min read1,420 views
httprange-requests206resumable-downloadnodejs

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

  1. Client probe: Client makes a HEAD request. The server replies with Accept-Ranges: bytes.
  2. Range request: Client sends Range: bytes=0-1048575 (requesting the first 1MB).
  3. Partial response: Server returns HTTP 206 Partial Content with:
    • Content-Range: bytes 0-1048575/10485760
    • Content-Length: 1048576
Verified Test Asset.pdf

Test HTTP byte range requests with curl against our 10MB PDF sample.

Download 10MB PDF Sample →

Testing Byte Ranges with cURL

Terminal
# 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

TypeScript
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);
}
NDL

Nguyen Dai Long

Author

Backend 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.

0/3000

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.

Related Articles