denoland/celldPublic

self-hosted, distributed Durable Objects

fetch() does not decompress gzip responses

MA

`fetch()` appears to return the raw gzip-compressed response body instead of transparently decompressing it.

Minimal repro:

```js const res = await fetch('https://httpbin.org/gzip')

console.log(res.status) console.log(res.headers.get('content-encoding')) console.log(await res.text()) ```

Observed:

```txt 200 gzip <binary gzip data> ```

Expected:

```txt 200 gzip { "gzipped": true, ... } ```

`Response.text()` should expose the decompressed body.

  1. nickchomeyunsubscribedlast month on GitHub

  2. MA
    Author

    Confirmed this still reproduces on **celld 0.6.2**, compared against **workerd 1.20261008.1** locally on Linux x86_64, with compatibility date `2026-10-08`.

    I used the same Worker source in both runtimes, fetching a deterministic local HTTP fixture instead of httpbin. The fixture always returns a 55-byte gzip body with `Content-Encoding: gzip`; the uncompressed JSON is 35 bytes:

    ```json {"gzipped":true,"message":"hello"} ```

    | API | workerd | celld 0.6.2 | | --- | --- | --- | | `res.text()` | Decoded JSON text | Raw gzip interpreted as text | | `res.json()` | Parses successfully | Throws `SyntaxError` | | `res.arrayBuffer()` | 35 decoded bytes | 55 compressed bytes | | First bytes | `7b 22` (`{"`) | `1f 8b` (gzip magic) |

    Both return status 200 and retain `Content-Encoding: gzip`. No manual decompression or compatibility flags were used. Reproduced twice.

    This affects consuming compressed upstream responses with `.text()` or `.json()`, including web-data extraction.