encode/httpx · error · ImportError

Using 'ZStandardDecoder', ...Make sure to install httpx usin

Error message

Using 'ZStandardDecoder', ...Make sure to install httpx using `pip install httpx[zstd]`.

What it means

ImportError raised in ZStandardDecoder.__init__ when the zstandard package is not importable but a response arrives with 'Content-Encoding: zstd'. Like brotli, httpx pops 'zstd' from SUPPORTED_DECODERS at import time when the package is missing, so this is most often seen when manually constructing the decoder or when the package state is inconsistent. The fix is to install the zstd extra.

Source

Thrown at httpx/_decoders.py:172

                # errors if a truncated or damaged data stream has been used.
                self.decompressor.finish()  # pragma: no cover
            return b""
        except brotli.error as exc:  # pragma: no cover
            raise DecodingError(str(exc)) from exc


class ZStandardDecoder(ContentDecoder):
    """
    Handle 'zstd' RFC 8878 decoding.

    Requires `pip install zstandard`.
    Can be installed as a dependency of httpx using `pip install httpx[zstd]`.
    """

    # inspired by the ZstdDecoder implementation in urllib3
    def __init__(self) -> None:
        if zstandard is None:  # pragma: no cover
            raise ImportError(
                "Using 'ZStandardDecoder', ..."
                "Make sure to install httpx using `pip install httpx[zstd]`."
            ) from None

        self.decompressor = zstandard.ZstdDecompressor().decompressobj()
        self.seen_data = False

    def decode(self, data: bytes) -> bytes:
        assert zstandard is not None
        self.seen_data = True
        output = io.BytesIO()
        try:
            output.write(self.decompressor.decompress(data))
            while self.decompressor.eof and self.decompressor.unused_data:
                unused_data = self.decompressor.unused_data
                self.decompressor = zstandard.ZstdDecompressor().decompressobj()
                output.write(self.decompressor.decompress(unused_data))
        except zstandard.ZstdError as exc:

View on GitHub (pinned to b5addb64f0)

Solutions

  1. Install the extra: `pip install httpx[zstd]`.
  2. Or directly: `pip install zstandard`.
  3. Pin in pyproject: `httpx[zstd]>=0.27`.
  4. Without installing, opt out: headers={'Accept-Encoding': 'gzip, deflate'} (no zstd).

Example fix

// before
pip install httpx
resp = client.get(url)  # Cloudflare sends Content-Encoding: zstd
resp.content  # ImportError
// after
pip install 'httpx[zstd]'
# or opt out:
resp = client.get(url, headers={'Accept-Encoding': 'gzip, deflate'})
Defensive patterns

Strategy: validation

Validate before calling

try:
    import zstandard  # noqa: F401
    HAS_ZSTD = True
except ImportError:
    HAS_ZSTD = False

headers = {'Accept-Encoding': 'gzip, deflate, zstd'} if HAS_ZSTD else {'Accept-Encoding': 'gzip, deflate'}
resp = client.get(url, headers=headers)

Type guard

def supports_zstd() -> bool:
    try:
        import zstandard  # noqa: F401
        return True
    except ImportError:
        return False

Try / catch

try:
    body = resp.content
except ImportError as exc:
    if 'zstd' in str(exc).lower() or 'zstandard' in str(exc).lower():
        import subprocess; subprocess.check_call(['pip', 'install', 'httpx[zstd]'])
    else:
        raise

Prevention

When it happens

Trigger: Response with 'Content-Encoding: zstd' without zstandard installed (zstd is increasingly common via Cloudflare, Facebook, AWS); manually building ZStandardDecoder() in tests; lockfile missing the optional extra.

Common situations: Hitting endpoints fronted by Cloudflare (zstd enabled by default since 2023); fresh pip install httpx without extras; slim Docker images; requirements file that lists httpx but not the zstd extra.

Related errors


AI-assisted analysis of encode/httpx@b5addb64f0 (2026-08-04). Data as JSON: /data/errors/1b9c3951621dc23d.json. Report an issue: GitHub.