HTTP partial content, resolved

What does your
Range request return?

Paste a Range header — bytes=0-499, bytes=500-, a suffix like bytes=-500, or a multi-range — plus the resource size. rangelab resolves the byte intervals, tells you whether it’s satisfiable, and shows the exact response — 206 (single or multipart), 416, or an ignored-Range 200 — with the precise Content-Range and Content-Length. It also validates a Content-Range.

Try:

unit: bytes

206 Partial Content

One satisfiable range → the server sends just that slice.

0-499bytes 0–499 · 500 bytes

Bytes 0 through 499.

Expected response
HTTP/1.1 206 Partial Content
Accept-Ranges: bytes
Content-Range: bytes 0-499/1234
Content-Length: 500

Resolved in your browser from the values you paste — nothing is uploaded, no live request is made. rangelab follows RFC 9110; confirm against your real server. How it’s computed →

Static resolution of the RFC 9110 Range rules from what you paste — no live request. Confirm against your real server.

What it shows

Every byte-range spec, resolved

The resolved intervals

Each spec parsed to a real byte interval against the size — with clamping of out-of-range ends and a visual bar of the slice.

206, 416, or 200

The exact status: 206 Partial Content when satisfiable, 416 when not, or a full 200 when a malformed Range is ignored.

The precise headers

Content-Range, Content-Length, and Accept-Ranges as the server should send them — single range or multipart/byteranges.

Suffix & multi-range

Handles bytes=-500 (the last 500 bytes) and multi-ranges like bytes=0-0,-1, including the per-part Content-Range lines.

Content-Range validator

A second mode checks a Content-Range value — start ≤ end < total — including the */total form used with 416.

Nothing leaves your browser

100% static page, pure client-side JavaScript — no backend, no upload, no live request. Your values stay with you.

The rules in brief

How byte ranges actually work

Inclusive, zero-based

bytes=0-499 is the first 500 bytes (positions 0–499). bytes=500- means byte 500 to the end. Content-Length is the number of bytes actually sent.

Suffix ranges

bytes=-500 is the LAST 500 bytes, not the first. If the resource is smaller, you get all of it. bytes=-0 requests nothing and is unsatisfiable.

206 / 416 / 200

A satisfiable range → 206 Partial Content. None satisfiable → 416 with Content-Range: bytes */total. A malformed or ignored Range → the full 200.

Multiple ranges

Two or more satisfiable ranges return multipart/byteranges — one Content-Range per part, no single top-level one, and Content-Length covers the whole multipart body.

Where it bites

Resumable downloads (bytes=received-), media seeking (byte offset), and object stores / CDNs all depend on correct Range handling. Off-by-one in Content-Range breaks them.

Open methodology

Exactly how it’s resolved

No black box — every step follows RFC 9110 (HTTP Semantics), which absorbed the original RFC 7233 byte-range rules, so you can verify it against the spec.

Stated plainly: rangelab is an informational developer tool. It resolves the Range and Content-Range rules statically from the values you paste and does not make a live request, so it cannot see server-specific behavior, proxies, or CDNs that bend the rules. Always confirm against your real server — a server MAY ignore Range for any reason and return the full 200.

Frequently asked questions

What does rangelab do?

It demystifies HTTP Range (partial-content) requests. Paste a Range request header — for example bytes=0-499, bytes=500-, bytes=-500, or a multi-range like bytes=0-0,-1 — together with the resource size, and rangelab parses every byte-range spec, resolves the actual byte intervals against the size, and shows exactly what the server should return: 206 Partial Content (single or multipart/byteranges), 416 Range Not Satisfiable, or a full 200 when a malformed Range is ignored — with the precise Content-Range, Content-Length, and Accept-Ranges headers. A second mode validates a Content-Range response header. Everything runs in your browser; nothing is uploaded.

How do I read bytes=0-499?

Byte positions are zero-based and inclusive. bytes=0-499 requests the first 500 bytes — positions 0 through 499. bytes=500-999 is the next 500. bytes=500- (no end) means "from byte 500 to the end of the resource". So Content-Length for bytes=0-499 is 500, and the response carries Content-Range: bytes 0-499/<total>.

What is a suffix range like bytes=-500?

A leading minus makes it a SUFFIX range: bytes=-500 asks for the LAST 500 bytes of the resource, not bytes 0–500. If the resource is smaller than the suffix length (say 300 bytes), you simply get the whole thing. bytes=-0 requests zero bytes and is unsatisfiable. Suffix ranges are how a client grabs, say, the trailer of a file without knowing its exact length.

When does the server return 206 vs 416 vs 200?

206 Partial Content when at least one requested range is satisfiable — the body is that slice (or, for several ranges, a multipart/byteranges document). 416 Range Not Satisfiable when no range can be satisfied (for example the first byte is at or past the end of the resource); the response carries Content-Range: bytes */<total> so the client learns the real size. 200 OK (the full resource) when the Range is malformed and the server ignores it, or when the server simply chooses not to honor ranges.

What happens with multiple ranges?

A request like bytes=0-99,200-299 with more than one satisfiable range produces a 206 whose body is a multipart/byteranges document: each part has its own Content-Range header and the parts are separated by a boundary. There is no single top-level Content-Range in that case, and Content-Length covers the entire multipart body (the slices plus the boundary and part headers), so it is larger than the sum of the requested bytes. rangelab lists the per-part Content-Range lines for you.

How are out-of-range values handled?

A last-byte-pos beyond the end is clamped to the last byte (size − 1) — bytes=1000-99999 on a 1234-byte file becomes bytes 1000-1233. A first-byte-pos at or past the end makes that range unsatisfiable. If last-byte-pos is less than first-byte-pos (bytes=500-100), the whole header is invalid and SHOULD be ignored, giving a 200. rangelab shows the clamping and satisfiability for every spec.

What is Accept-Ranges, and Content-Range exactly?

Accept-Ranges: bytes is the server advertising that it supports byte ranges; Accept-Ranges: none means it will not honor them (so it answers 200). Content-Range is the response header that describes the slice being returned: bytes start-end/total (e.g. bytes 0-499/1234), bytes start-end/* when the total is not yet known, or bytes */total in a 416 response. It is valid only when start ≤ end and end < total — rangelab’s second mode checks exactly that.

Why do Range requests matter in practice?

They power three everyday things. Resumable downloads: after a dropped connection, the client re-requests bytes=<bytes-already-received>- to continue rather than restart. Media streaming and seeking: a video player jumps to a timestamp by requesting the byte offset for that point. And object stores / CDNs (S3, R2, Bunny, and friends) lean on correct Range handling for partial reads. A subtle off-by-one in Content-Range breaks all of them, which is what this tool helps you catch.

Is this exact? Is my data private?

rangelab implements the Range and Content-Range rules from RFC 9110 (HTTP Semantics), which absorbed the older RFC 7233. It evaluates statically from the values you paste and does not make a live request, so it cannot see server-specific behavior, proxies, or CDNs that bend the rules — always confirm against your real server. On privacy: this is a static page; everything you paste is processed in your browser, never uploaded, and nothing is logged.