According to RFC 1950 , the difference between the "OK" 0x789C and the "bad" 0x78DA is in the FLEVEL bit-field:

  FLEVEL (Compression level)
     These flags are available for use by specific compression
     methods.  The "deflate" method (CM = 8) sets these flags as
     follows:

        0 - compressor used fastest algorithm
        1 - compressor used fast algorithm
        2 - compressor used default algorithm
        3 - compressor used maximum compression, slowest algorithm

     The information in FLEVEL is not needed for decompression; it
     is there to indicate if recompression might be worthwhile.

"OK" uses 2, "bad" uses 3. So that difference in itself is not a problem.

To get any further, you might consider supplying the following information for each of compressing and (attempted) decompressing: what platform, what version of Python, what version of the zlib library, what was the actual code used to call the zlib module. Also supply the full traceback and error message from the failing decompression attempts. Have you tried to decompress the failing files with any other zlib-reading software? With what results? Please clarify what you have to work with: Does "Am I hosed?" mean that you don't have access to the original data? How did it get from a stream to a file? What guarantee do you have that the data was not mangled in transmission?

UPDATE Some observations based on partial clarifications published in your self-answer:

You are using Windows. Windows distinguishes between binary mode and text mode when reading and writing files. When reading in text mode, Python 2.x changes '\r\n' to '\n', and changes '\n' to '\r\n' when writing. This is not a good idea when dealing with non-text data. Worse, when reading in text mode, '\x1a' aka Ctrl-Z is treated as end-of-file.

To compress a file:

# imports and other superstructure left as a exercise
str_object1 = open('my_log_file', 'rb').read()
str_object2 = zlib.compress(str_object1, 9)
f = open('compressed_file', 'wb')
f.write(str_object2)
f.close()

To decompress a file:

str_object1 = open('compressed_file', 'rb').read()
str_object2 = zlib.decompress(str_object1)
f = open('my_recovered_log_file', 'wb')
f.write(str_object2)
f.close()

Aside: Better to use the gzip module which saves you having to think about nasssties like text mode, at the cost of a few bytes for the extra header info.

If you have been using 'rb' and 'wb' in your compression code but not in your decompression code [unlikely?], you are not hosed, you just need to flesh out the above decompression code and go for it.

Note carefully the use of "may", "should", etc in the following untested ideas.

If you have not been using 'rb' and 'wb' in your compression code, the probability that you have hosed yourself is rather high.

If there were any instances of '\x1a' in your original file, any data after the first such is lost -- but in that case it shouldn't fail on decompression (IOW this scenario doesn't match your symptoms).

If a Ctrl-Z was generated by zlib itself, this should cause an early EOF upon attempted decompression, which should of course cause an exception. In this case you may be able to gingerly reverse the process by reading the compressed file in binary mode and then substitute '\r\n' with '\n' [i.e. simulate text mode without the Ctrl-Z -> EOF gimmick]. Decompress the result. Edit Write the result out in TEXT mode. End edit

UPDATE 2 I can reproduce your symptoms -- with ANY level 1 to 9 -- with the following script:

import zlib, sys
fn = sys.argv[1]
level = int(sys.argv[2])
s1 = open(fn).read() # TEXT mode
s2 = zlib.compress(s1, level)
f = open(fn + '-ct', 'w') # TEXT mode
f.write(s2)
f.close()
# try to decompress in text mode
s1 = open(fn + '-ct').read() # TEXT mode
s2 = zlib.decompress(s1) # error -5
f = open(fn + '-dtt', 'w')
f.write(s2)
f.close()

Note: you will need a use a reasonably large text file (I used an 80kb source file) to ensure that the decompression result will contain a '\x1a'.

I can recover with this script:

import zlib, sys
fn = sys.argv[1]
# (1) reverse the text-mode write
# can't use text-mode read as it will stop at Ctrl-Z
s1 = open(fn, 'rb').read() # BINARY mode
s1 = s1.replace('\r\n', '\n')
# (2) reverse the compression
s2 = zlib.decompress(s1)
# (3) reverse the text mode read
f = open(fn + '-fixed', 'w') # TEXT mode
f.write(s2)
f.close()

NOTE: If there is a '\x1a' aka Ctrl-Z byte in the original file, and the file is read in text mode, that byte and all following bytes will NOT be included in the compressed file, and thus can NOT be recovered. For a text file (e.g. source code), this is no loss at all. For a binary file, you are most likely hosed.

Update 3 [following late revelation that there's an encryption/decryption layer involved in the problem]:

The "Error -5" message indicates that the data that you are trying to decompress has been mangled since it was compressed. If it's not caused by using text mode on the files, suspicion obviously(?) falls on your decryption and encryption wrappers. If you want help, you need to divulge the source of those wrappers. In fact what you should try to do is (like I did) put together a small script that reproduces the problem on more than one input file. Secondly (like I did) see whether you can reverse the process under what conditions. If you want help with the second stage, you need to divulge the problem-reproduction script.

Answer from John Machin on Stack Overflow
🌐
Python
docs.python.org › 3 › library › zlib.html
zlib — Compression compatible with gzip
+40 to +47 = 32 + (8 to 15): Uses the low 4 bits of the value as the window size logarithm, and automatically accepts either the zlib or gzip format. When decompressing a stream, the window size must not be smaller than the size originally used to compress the stream; using a too-small value may result in an error exception.
Top answer
1 of 4
36

According to RFC 1950 , the difference between the "OK" 0x789C and the "bad" 0x78DA is in the FLEVEL bit-field:

  FLEVEL (Compression level)
     These flags are available for use by specific compression
     methods.  The "deflate" method (CM = 8) sets these flags as
     follows:

        0 - compressor used fastest algorithm
        1 - compressor used fast algorithm
        2 - compressor used default algorithm
        3 - compressor used maximum compression, slowest algorithm

     The information in FLEVEL is not needed for decompression; it
     is there to indicate if recompression might be worthwhile.

"OK" uses 2, "bad" uses 3. So that difference in itself is not a problem.

To get any further, you might consider supplying the following information for each of compressing and (attempted) decompressing: what platform, what version of Python, what version of the zlib library, what was the actual code used to call the zlib module. Also supply the full traceback and error message from the failing decompression attempts. Have you tried to decompress the failing files with any other zlib-reading software? With what results? Please clarify what you have to work with: Does "Am I hosed?" mean that you don't have access to the original data? How did it get from a stream to a file? What guarantee do you have that the data was not mangled in transmission?

UPDATE Some observations based on partial clarifications published in your self-answer:

You are using Windows. Windows distinguishes between binary mode and text mode when reading and writing files. When reading in text mode, Python 2.x changes '\r\n' to '\n', and changes '\n' to '\r\n' when writing. This is not a good idea when dealing with non-text data. Worse, when reading in text mode, '\x1a' aka Ctrl-Z is treated as end-of-file.

To compress a file:

# imports and other superstructure left as a exercise
str_object1 = open('my_log_file', 'rb').read()
str_object2 = zlib.compress(str_object1, 9)
f = open('compressed_file', 'wb')
f.write(str_object2)
f.close()

To decompress a file:

str_object1 = open('compressed_file', 'rb').read()
str_object2 = zlib.decompress(str_object1)
f = open('my_recovered_log_file', 'wb')
f.write(str_object2)
f.close()

Aside: Better to use the gzip module which saves you having to think about nasssties like text mode, at the cost of a few bytes for the extra header info.

If you have been using 'rb' and 'wb' in your compression code but not in your decompression code [unlikely?], you are not hosed, you just need to flesh out the above decompression code and go for it.

Note carefully the use of "may", "should", etc in the following untested ideas.

If you have not been using 'rb' and 'wb' in your compression code, the probability that you have hosed yourself is rather high.

If there were any instances of '\x1a' in your original file, any data after the first such is lost -- but in that case it shouldn't fail on decompression (IOW this scenario doesn't match your symptoms).

If a Ctrl-Z was generated by zlib itself, this should cause an early EOF upon attempted decompression, which should of course cause an exception. In this case you may be able to gingerly reverse the process by reading the compressed file in binary mode and then substitute '\r\n' with '\n' [i.e. simulate text mode without the Ctrl-Z -> EOF gimmick]. Decompress the result. Edit Write the result out in TEXT mode. End edit

UPDATE 2 I can reproduce your symptoms -- with ANY level 1 to 9 -- with the following script:

import zlib, sys
fn = sys.argv[1]
level = int(sys.argv[2])
s1 = open(fn).read() # TEXT mode
s2 = zlib.compress(s1, level)
f = open(fn + '-ct', 'w') # TEXT mode
f.write(s2)
f.close()
# try to decompress in text mode
s1 = open(fn + '-ct').read() # TEXT mode
s2 = zlib.decompress(s1) # error -5
f = open(fn + '-dtt', 'w')
f.write(s2)
f.close()

Note: you will need a use a reasonably large text file (I used an 80kb source file) to ensure that the decompression result will contain a '\x1a'.

I can recover with this script:

import zlib, sys
fn = sys.argv[1]
# (1) reverse the text-mode write
# can't use text-mode read as it will stop at Ctrl-Z
s1 = open(fn, 'rb').read() # BINARY mode
s1 = s1.replace('\r\n', '\n')
# (2) reverse the compression
s2 = zlib.decompress(s1)
# (3) reverse the text mode read
f = open(fn + '-fixed', 'w') # TEXT mode
f.write(s2)
f.close()

NOTE: If there is a '\x1a' aka Ctrl-Z byte in the original file, and the file is read in text mode, that byte and all following bytes will NOT be included in the compressed file, and thus can NOT be recovered. For a text file (e.g. source code), this is no loss at all. For a binary file, you are most likely hosed.

Update 3 [following late revelation that there's an encryption/decryption layer involved in the problem]:

The "Error -5" message indicates that the data that you are trying to decompress has been mangled since it was compressed. If it's not caused by using text mode on the files, suspicion obviously(?) falls on your decryption and encryption wrappers. If you want help, you need to divulge the source of those wrappers. In fact what you should try to do is (like I did) put together a small script that reproduces the problem on more than one input file. Secondly (like I did) see whether you can reverse the process under what conditions. If you want help with the second stage, you need to divulge the problem-reproduction script.

2 of 4
4

I was looking for

python -c 'import sys,zlib;sys.stdout.write(zlib.decompress(sys.stdin.read()))'

wrote it myself; based on answers of zlib decompression in python

Discussions

How to decompress base64 zlib data in Python?
I have tile map graphical data compressed with . And in python, I’m trying to decompress that to get back the original data as a readable string or an array of nums. The compressed … More on discourse.mapeditor.org
🌐 discourse.mapeditor.org
2
0
March 16, 2023
parsing - Python script for zlib decompression - Code Review Stack Exchange
I'm looking for feedback/improvement on code that I wrote. It's a function that scans a file for zlib headers and returns the header, offset, and decompressed data. In main, below the function, I use More on codereview.stackexchange.com
🌐 codereview.stackexchange.com
April 23, 2022
Can't decompress a particular PDF's /FlateDecode stream using PHP's gzuncompress, or any alternatives - any ideas?
I don't know the quirks of PDF parsing well enough to point you to a solution, but since there are existing PDF parsers that can handle it, if I were in your position I'd be inclined to find an existing open source parser that handles it, and run it with a debugger, to see how it handles this stream. More on reddit.com
🌐 r/AskProgramming
3
3
August 22, 2024
Analyzing Python Compression Libraries: zlib, LZ4, Brotli, and Zstandard
You need to compare levels to make this useful. Brotli defaults to the maximum level (11) which is why its taking so long -- if you turn it down to 6 you'll get a ~1.17s compression time with a ~57% ratio. Zstandard defaults to 3 on a scale of 22. If you turn it up to 22 you'll get a >100 second compression time and a ~60% ratio. If you go 6 for Brotli and 11 for Zstandard you'll get roughly the same speed (for compression) and ratio. Point is, level matters a lot. There's other factors like streaming performance and window size that you need to account for but bare minimum you need to do like-to-like comparisons on level. More on reddit.com
🌐 r/Python
15
23
April 30, 2024
🌐
GeeksforGeeks
geeksforgeeks.org › python › zlib-decompresss-in-python
zlib.decompress(s) in Python - GeeksforGeeks
March 6, 2020 - Syntax : zlib.decompress(string) Return : Return decompressed string.
🌐
GitHub
github.com › oliverbaileysmith › zlib-decompress
GitHub - oliverbaileysmith/zlib-decompress: Python implementation of ZLIB decompression · GitHub
A Python implementation of decompression of ZLIB compressed data. decompress.py contains the user-facing function decompress which takes in data compressed by zlib.compress and returns the decompressed data.
Author   oliverbaileysmith
🌐
Stack Abuse
stackabuse.com › python-zlib-library-tutorial
Python zlib Library Tutorial
July 17, 2023 - This example is very similar to the previous one in that we're decompressing data that originates from a file, except that in this case we're going back to using the one-off decompress method, which decompresses the data in a single method call. This is useful for when your data is small enough to easily fit in memory. ... import zlib compressed_data = open('compressed.dat', 'rb').read() decompressed_data = zlib.decompress(compressed_data) print(decompressed_data)
🌐
MicroPython
docs.micropython.org › en › latest › library › zlib.html
zlib – zlib compression & decompression — MicroPython latest documentation
This module implements a subset of the corresponding CPython module, as described below. For more information, refer to the original CPython documentation: zlib. This module allows compression and decompression of binary data with the DEFLATE algorithm (commonly used in the zlib library and ...
🌐
Tiled Forum
discourse.mapeditor.org › questions
How to decompress base64 zlib data in Python? - Questions - Tiled Forum
March 16, 2023 - I have tile map graphical data compressed with <encoding=“base64” compression=“zlib”>. And in python, I’m trying to decompress that to get back the original data as a readable string or an array of nums. The compressed …
🌐
Pyokagan
pyokagan.name › blog › 2019-10-18-zlibinflate
Let's implement zlib.decompress()
October 18, 2019 - Bits 0 to 3: CM --- Compression Method. This identifies the compression method in the file. Only CM=8 is defined by the zlib spec, which basically says that the zlib file contains data compressed with DEFLATE.
Find elsewhere
🌐
W3Schools
w3schools.com › python › ref_module_zlib.asp
Python zlib Module
Python Examples Python Compiler Python Exercises Python Quiz Python Challenges Python Practice Problems Python Server Python Syllabus Python Study Plan Python Interview Q&A Python Bootcamp Python Training ... import zlib text = b'Hello Tobias! This is a message to compress.' compressed = zlib.compress(text) decompressed = zlib.decompress(compressed) print(f'Original size: {len(text)} bytes') print(f'Compressed size: {len(compressed)} bytes') print(f'Decompressed: {decompressed.decode()}') Try it Yourself »
🌐
Delft Stack
delftstack.com › home › howto › python › python zlib
How to Compress and Decompress Data Using Zlib in Python | Delft Stack
February 2, 2024 - The following code snippet demonstrates how to decompress the previously compressed data with Python’s zlib.decompress() function.
🌐
CircuitPython
docs.circuitpython.org › en › latest › shared-bindings › zlib
zlib – zlib decompression functionality — Adafruit CircuitPython 1 documentation
The zlib module allows limited functionality similar to the CPython zlib library. This module allows to decompress binary data compressed with DEFLATE algorithm (commonly used in zlib library and gzip archiver).
🌐
Jon
jon.glass › blog › has-fun-with-zlib
Use Python zlib to recover Zip Files – Half Full of Security
November 25, 2014 - Deflate is passing data to the zlib.compress function and then it removes the first two bytes(the zlib compression header (0x78 0x9C)) and the last four bytes which contain the checksum. After removing that metadata we are left raw deflated data, exactly like you would find inside of a zip file. The inflate function is fairly simple as well. It passes compressed data to the zlib decompress function with a windowbits size of -15.
🌐
Python
docs.python.org › 3.4 › library › zlib.html
13.1. zlib — Compression compatible with gzip — Python 3.4.10 documentation
June 16, 2019 - For applications that require data compression, the functions in this module allow compression and decompression, using the zlib library. The zlib library has its own home page at http://www.zlib.net.
🌐
GitHub
gist.github.com › tbarabosch › 96f2afc0ddfae4ac0bb2a3e22f781b17
[python] Decompress zlib compressed binary blobs · GitHub
[python] Decompress zlib compressed binary blobs. GitHub Gist: instantly share code, notes, and snippets.
🌐
w3resource
w3resource.com › python-exercises › extended-data-types › python-extended-data-types-bytes-bytearrays-exercise-8.php
Python Program: Compress and decompress bytes using zlib
August 11, 2025 - The "decompress_bytes()" function decompresses the compressed bytes using the "zlib.decompress()" function. In the "main()" function, a sample sequence of bytes is compressed, decompressed, and the original, compressed, and decompressed results ...
🌐
Python Module of the Week
pymotw.com › 2 › zlib
zlib – Low-level access to GNU zlib compression library - Python Module of the Week
Compressed : 32 789c0bc9c82c5600a2928c5485fca2ccf4ccbcc41c8592d48a123d007f2f097e Decompressed : 26 This is the original text. Notice that for short text, the compressed version can be longer. While the actual results depend on the input data, for short bits of text it is interesting to observe the compression overhead. import zlib original_data = 'This is the original text.' fmt = 's s' print fmt % ('len(data)', 'len(compressed)') print fmt % ('-' * 15, '-' * 15) for i in xrange(20): data = original_data * i compressed = zlib.compress(data) print fmt % (len(data), len(compressed)), '*' if len(data) < len(compressed) else ''
🌐
GeeksforGeeks
geeksforgeeks.org › zlib-compresss-in-python
zlib.compress(s) in python - GeeksforGeeks
March 6, 2020 - python · zlib.decompress(s) in Python · With the help of zlib.decompress(s) method, we can decompress the compressed bytes of string into original string by using zlib.decompress(s) method.
🌐
Bomberbot
bomberbot.com › python › zlib-decompression-in-python-unlocking-compressed-data
Zlib Decompression in Python: Unlocking Compressed Data - Bomberbot
July 18, 2025 - This function handles both gzip and deflate compression methods, which are commonly used by web servers. The 16 + zlib.MAX_WBITS parameter for gzip decompression tells zlib to expect a gzip header. While Python's zipfile module is typically used for handling ZIP files, understanding zlib decompression allows you to work with ZIP contents at a lower level.