online / endpoints 62 / categories 10 / rate 60/min/ip /

GET /range

GET /range alias: /range

Returns correct HTTP Range responses: 206 with the exact requested bytes and an accurate Content-Range header, 416 for unsatisfiable ranges, 200 + full body on If-Range ETag mismatch. Counterpart to /range, which lies about which bytes it returns.

expect: Send a Range header to get 206 with the correct byte slice. Omit it for 200 with the full 1000-byte document. Send an If-Range header with a mismatched ETag to get 200 + full body per RFC 9110 §13.1.5.

bash
curl -si -H 'Range: bytes=0-99' 'https://not.catastrophic.io/range' | grep -E '^(HTTP|content-type|content-range|content-length|x-chaos-range)'
# Default mode (accepts-range-lies) ACKs the requested range in
# Content-Range but ships bytes from a different offset. Clients
# that trust Content-Range to track stream position silently
# corrupt the reassembled file — the lie only surfaces when a
# final checksum fails.
import urllib.request
req = urllib.request.Request("https://not.catastrophic.io/range", headers={"Range": "bytes=0-99"})
resp = urllib.request.urlopen(req)
print("Status:", resp.status)
print("Content-Range:", resp.headers.get("Content-Range"))
print("X-Chaos-Range-Actual:", resp.headers.get("X-Chaos-Range-Actual"))
print("X-Chaos-Range-Mode:", resp.headers.get("X-Chaos-Range-Mode"))
body = resp.read()
print("body bytes:", len(body))
print("first 20 bytes:", body[:20])
const res = await fetch("https://not.catastrophic.io/range", { headers: { Range: "bytes=0-99" } });
console.log("Status:", res.status);
console.log("Content-Range:", res.headers.get("content-range"));
console.log("X-Chaos-Range-Actual:", res.headers.get("x-chaos-range-actual"));
console.log("X-Chaos-Range-Mode:", res.headers.get("x-chaos-range-mode"));
const buf = await res.arrayBuffer();
console.log("body bytes:", buf.byteLength);
package main

import (
    "fmt"
    "io"
    "net/http"
)

func main() {
    req, _ := http.NewRequest("GET", "https://not.catastrophic.io/range", nil)
    req.Header.Set("Range", "bytes=0-99")
    resp, _ := http.DefaultClient.Do(req)
    defer resp.Body.Close()
    fmt.Println("Status:", resp.StatusCode)
    fmt.Println("Content-Range:", resp.Header.Get("Content-Range"))
    fmt.Println("X-Chaos-Range-Actual:", resp.Header.Get("X-Chaos-Range-Actual"))
    fmt.Println("X-Chaos-Range-Mode:", resp.Header.Get("X-Chaos-Range-Mode"))
    body, _ := io.ReadAll(resp.Body)
    fmt.Println("body bytes:", len(body))
}
// Cargo.toml: reqwest = { version = "0.12", features = ["blocking"] }
fn main() -> Result<(), Box> {
    let client = reqwest::blocking::Client::new();
    let resp = client.get("https://not.catastrophic.io/range").header("Range", "bytes=0-99").send()?;
    println!("Status: {}", resp.status());
    println!("Content-Range: {:?}", resp.headers().get("content-range"));
    println!("X-Chaos-Range-Actual: {:?}", resp.headers().get("x-chaos-range-actual"));
    let body = resp.bytes()?;
    println!("body bytes: {}", body.len());
    Ok(())
}
import java.net.URI;
import java.net.http.*;

public class RangeChaos {
    public static void main(String[] args) throws Exception {
        var client = HttpClient.newHttpClient();
        var req = HttpRequest.newBuilder(URI.create("https://not.catastrophic.io/range"))
            .header("Range", "bytes=0-99")
            .build();
        var resp = client.send(req, HttpResponse.BodyHandlers.ofByteArray());
        System.out.println("Status: " + resp.statusCode());
        System.out.println("Content-Range: " + resp.headers().firstValue("Content-Range").orElse(""));
        System.out.println("X-Chaos-Range-Mode: " + resp.headers().firstValue("X-Chaos-Range-Mode").orElse(""));
        System.out.println("body bytes: " + resp.body().length);
    }
}
using var client = new HttpClient();
var req = new HttpRequestMessage(HttpMethod.Get, "https://not.catastrophic.io/range");
req.Headers.Range = new System.Net.Http.Headers.RangeHeaderValue(0, 99);
var resp = await client.SendAsync(req);
Console.WriteLine($"Status: {(int)resp.StatusCode}");
Console.WriteLine($"Content-Range: {resp.Content.Headers.ContentRange}");
Console.WriteLine($"X-Chaos-Range-Mode: {resp.Headers.GetValues("X-Chaos-Range-Mode").FirstOrDefault()}");
var body = await resp.Content.ReadAsByteArrayAsync();
Console.WriteLine($"body bytes: {body.Length}");
require "net/http"
uri = URI("https://not.catastrophic.io/range")
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
    req = Net::HTTP::Get.new(uri.request_uri, "Range" => "bytes=0-99")
    res = http.request(req)
    puts "Status: #{res.code}"
    puts "Content-Range: #{res['Content-Range']}"
    puts "X-Chaos-Range-Actual: #{res['X-Chaos-Range-Actual']}"
    puts "X-Chaos-Range-Mode: #{res['X-Chaos-Range-Mode']}"
    puts "body bytes: #{res.body.bytesize}"
end
$r = Invoke-WebRequest -Uri 'https://not.catastrophic.io/range' -Headers @{ 'Range' = 'bytes=0-99' }
"Status: $($r.StatusCode)"
"Content-Range: $($r.Headers['Content-Range'])"
"X-Chaos-Range-Actual: $($r.Headers['X-Chaos-Range-Actual'])"
"X-Chaos-Range-Mode: $($r.Headers['X-Chaos-Range-Mode'])"
"body bytes: $($r.RawContentLength)"