{"id":468,"library":"brotli","title":"Brotli Compression Library","description":"Python bindings for the Brotli compression library. It offers high-performance lossless compression, often achieving better ratios than gzip, particularly for text-based data. The library's releases are typically synchronized with updates to the underlying C Brotli reference implementation.","status":"active","version":"1.2.0","language":"python","source_language":"en","source_url":"https://github.com/google/brotli","tags":["compression","brotli","data-compression","security"],"install":[{"cmd":"pip install brotli","lang":"bash","label":"Install latest stable version"}],"dependencies":[],"imports":[{"symbol":"brotli","correct":"import brotli"},{"note":"For one-shot compression of bytes.","symbol":"compress","correct":"brotli.compress(data)"},{"note":"For one-shot decompression of bytes.","symbol":"decompress","correct":"brotli.decompress(compressed_data)"},{"note":"For streaming compression.","symbol":"Compressor","correct":"compressor = brotli.Compressor()"},{"note":"For streaming decompression.","symbol":"Decompressor","correct":"decompressor = brotli.Decompressor()"},{"note":"The exception raised for compression/decompression failures or invalid arguments.","symbol":"error","correct":"try: ... except brotli.error: ..."}],"quickstart":{"code":"import brotli\n\n# Example data (must be bytes)\noriginal_data = b\"This is some sample text data that we want to compress. It's repetitive and will benefit from Brotli's algorithm.\"\n\n# Compress data with default quality (11, highest compression)\n# quality can range from 0 (fastest) to 11 (highest compression ratio)\ncompressed_data = brotli.compress(original_data, quality=5)\n\nprint(f\"Original size: {len(original_data)} bytes\")\nprint(f\"Compressed size: {len(compressed_data)} bytes\")\n\n# Decompress data\ndecompressed_data = brotli.decompress(compressed_data)\n\nprint(f\"Decompressed size: {len(decompressed_data)} bytes\")\nprint(f\"Data matches original: {original_data == decompressed_data}\")\n\n# Example of streaming compression\ncompressor = brotli.Compressor(quality=4)\nstreaming_compressed = b''\n\nfor i in range(3):\n    chunk = b'chunk ' + str(i).encode() + b' of data\\n'\n    streaming_compressed += compressor.process(chunk)\nstreaming_compressed += compressor.finish()\n\nprint(f\"\\nStreaming compressed size: {len(streaming_compressed)} bytes\")\n\n# Example of streaming decompression (with output_buffer_limit for safety)\ndecompressor = brotli.Decompressor()\nstreaming_decompressed = b''\nmax_output_len = 1024 # Set a reasonable limit\n\ntry:\n    # process might raise brotli.error if output_buffer_limit is exceeded\n    for chunk in [streaming_compressed]: # In real usage, this would be chunks of compressed data\n        streaming_decompressed += decompressor.process(chunk, output_buffer_limit=max_output_len)\n    streaming_decompressed += decompressor.finish()\n    print(f\"Streaming decompressed size: {len(streaming_decompressed)} bytes\")\nexcept brotli.error as e:\n    print(f\"Decompression error: {e}\")\n    print(\"Output buffer limit likely exceeded or corrupted data.\")","lang":"python","description":"This quickstart demonstrates basic one-shot compression and decompression, as well as a simple streaming compression and decompression using `brotli.Compressor` and `brotli.Decompressor`. It also shows how to handle the `output_buffer_limit` introduced in v1.2.0 for security."},"warnings":[{"fix":"Upgrade to brotli v1.2.0 or newer. For streaming decompression, actively use the `output_buffer_limit` parameter in `Decompressor.process()` and handle `brotli.error` if the limit is exceeded.","message":"Older versions (<= 1.1.0) are vulnerable to Denial of Service (DoS) attacks via 'decompression bombs' (e.g., highly compressed zero-filled data expanding to excessive sizes), leading to memory exhaustion. Version 1.2.0 introduces `Decompressor::can_accept_more_data` and an optional `output_buffer_limit` argument to `Decompressor::process` to mitigate this.","severity":"breaking","affected_versions":"<= 1.1.0"},{"fix":"Upgrade to brotli v1.0.9 or newer.","message":"Versions of brotli prior to v1.0.9 were vulnerable to an integer overflow in the decoder when processing input chunks larger than 2GiB (CVE-2020-8927).","severity":"gotcha","affected_versions":"<= 1.0.8"},{"fix":"Wrap decompression calls in a `try...except brotli.error` block to gracefully handle invalid input.","message":"Attempting to decompress data that was not compressed with Brotli will raise a `brotli.error` exception. Ensure the input data is valid Brotli compressed data.","severity":"gotcha","affected_versions":"All"},{"fix":"Always call `compressor.finish()` after feeding all data chunks to `compressor.process()` to ensure all remaining data is emitted.","message":"When using `brotli.Compressor` for streaming compression, it's crucial to call the `.finish()` method at the end of the data stream. Failing to do so will result in an incomplete or corrupted compressed output, as buffered data may not be flushed.","severity":"gotcha","affected_versions":"All"},{"fix":"Always open files for Brotli operations with `b` in the mode string (e.g., `open('file.br', 'wb')`).","message":"When interacting with files, Brotli operates on raw bytes. Files must be opened in binary mode (`'rb'` for reading, `'wb'` for writing) to avoid `TypeError` or unexpected corruption.","severity":"gotcha","affected_versions":"All"},{"fix":"Check the `Content-Encoding` header or the documentation of your HTTP client to determine if automatic decompression is occurring before attempting manual decompression.","message":"HTTP client libraries like `requests` and `urllib3` automatically detect and decompress Brotli (and other) encodings if the `brotli` library is installed. If you attempt to manually decompress content that has already been automatically decompressed, it will result in `brotli.error`.","severity":"gotcha","affected_versions":"All"},{"fix":"Do not call `finish()` on a `brotli.Decompressor` object. For streaming decompression, feed all compressed data chunks into `decompressor.process()` until all data is decompressed.","message":"The `finish()` method is exclusive to the `brotli.Compressor` object for flushing remaining compressed data. The `brotli.Decompressor` object does not have a `finish()` method. Attempting to call it will result in an `AttributeError`.","severity":"breaking","affected_versions":"All"},{"fix":"Remove calls to `decompressor.finish()`. Ensure all output from `decompressor.process()` is collected during streaming decompression. When all input is processed, any remaining decompressed data will have been emitted by the last `decompressor.process()` call.","message":"The `brotli.Decompressor` object does not have a `finish()` method. Unlike `brotli.Compressor`, there is no explicit 'finish' step for decompressors. All decompressed output is returned by `decompressor.process()` as input chunks are fed, or when the final `process()` call is made with remaining input.","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"last_verified":"2026-05-12T14:03:26.007Z","next_check":"2026-06-26T00:00:00.000Z","problems":[{"fix":"Ensure you have the Microsoft Visual C++ Build Tools installed (available through Visual Studio Installer). Then, try uninstalling and reinstalling brotli: `pip uninstall brotli` followed by `pip install brotli`. It is also recommended to use a virtual environment.","cause":"This error typically occurs on Windows when the C extension for brotli is not properly built or found, often due to missing Visual C++ Build Tools or an incorrect Python environment.","error":"ModuleNotFoundError: No module named '_brotli' OR ImportError: DLL load failed while importing _brotli: The specified module could not be found."},{"fix":"First, try updating or reinstalling `brotli`: `pip install --upgrade brotli`. If the issue persists, explicitly uninstall both `brotli` and `brotlipy`/`brotlicffi` and then reinstall only `brotli`: `pip uninstall brotli brotlipy brotlicffi` then `pip install brotli`.","cause":"This error usually arises from a conflict between the `brotli` package and `brotlipy` (or `brotlicffi`), where another library's `import brotli` statement resolves to a different or older implementation that lacks the `error` exception class.","error":"AttributeError: module 'brotli' has no attribute 'error'"},{"fix":"On Windows, install the Microsoft Visual C++ Build Tools. On Linux, ensure you have build essentials (e.g., `sudo apt-get install build-essential` or `sudo yum groupinstall 'Development Tools'`). Then retry `pip install brotli`.","cause":"This installation error indicates that pip was unable to compile the C source code for the brotli Python bindings, most commonly due to missing C/C++ compiler tools or other build dependencies.","error":"ERROR: Could not build wheels for brotli"},{"fix":"Verify the integrity and completeness of the Brotli-compressed data you are trying to decompress. Ensure the data source is reliable and that the entire compressed stream is received before attempting decompression. If fetching from a server, check server-side compression settings and content delivery.","cause":"This error occurs when attempting to decompress data that is corrupted, truncated, or not valid Brotli compressed data.","error":"brotli.brotli.Error: Decompression error: incomplete compressed stream."}],"ecosystem":"pypi","meta_description":null,"install_score":80,"install_tag":"verified","quickstart_score":0,"quickstart_tag":"stale","pypi_latest":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0,"mem_mb":0,"disk_size":"21.5M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0,"mem_mb":0,"disk_size":"23M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0,"mem_mb":0,"disk_size":"23.3M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0,"mem_mb":0,"disk_size":"25M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0,"mem_mb":0,"disk_size":"15.2M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0,"mem_mb":0,"disk_size":"17M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0,"mem_mb":0,"disk_size":"14.8M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0,"mem_mb":0,"disk_size":"17M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0,"mem_mb":0,"disk_size":"21.0M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0,"mem_mb":0,"disk_size":"23M"}]},"quickstart_checks":{"last_tested":"2026-04-23","tag":"stale","tag_description":"widespread failures or data too old to trust","results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}