It is also possible to decompress it using standard shell-script + gzip, if you don't have, or want to use openssl or other tools.
The trick is to prepend the gzip magic number and compress method to the actual data from zlib.compress:

printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" |cat - /tmp/data |gzip -dc >/tmp/out

Edits:
@d0sboots commented: For RAW Deflate data, you need to add 2 more null bytes:
โ†’ "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00"

This Q on SO gives more information about this approach. An answer there suggests that there is also an 8 byte footer.

Users @Vitali-Kushner and @mark-bessey reported success even with truncated files, so a gzip footer does not seem strictly required.

@tobias-kienzler suggested this function for the bashrc:
zlibd() (printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" | cat - "$@" | gzip -dc)

Answer from wkpark on Stack Exchange
๐ŸŒ
zlib
zlib.net โ€บ zlib_how.html
zlib Usage Example
February 12, 2026 - /* Decompress from file source to file dest until stream ends or EOF. inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be allocated for processing, Z_DATA_ERROR if the deflate data is invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and the version of the library linked do not match, or Z_ERRNO if there is an error reading or writing the files.
๐ŸŒ
Stack Abuse
stackabuse.com โ€บ python-zlib-library-tutorial
Python zlib Library Tutorial
July 17, 2023 - The file is then decompressed using chunks of data. Again, in this example the file doesn't contain a massive amount of data, but nevertheless, it serves the purpose of explaining the buffer concept. ... import zlib data = 'Hello world' compress = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, +15) compressed_data = compress.compress(data) compressed_data += compress.flush() print('Original: ' + data) print('Compressed data: ' + compressed_data) f = open('compressed.dat', 'w') f.write(compressed_data) f.close() CHUNKSIZE = 1024 data2 = zlib.decompressobj() my_file = open('compressed.dat', 'rb') buf = my_file.read(CHUNKSIZE) # Decompress stream chunks while buf: decompressed_data = data2.decompress(buf) buf = my_file.read(CHUNKSIZE) decompressed_data += data2.flush() print('Decompressed data: ' + decompressed_data) my_file.close()
๐ŸŒ
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 ...
๐ŸŒ
GitHub
gist.github.com โ€บ arq5x โ€บ 5315739
Compress and then Decompress a string with zlib. ยท GitHub - Gist
// deflate a into b. (that is, compress a into b) // zlib struct z_stream defstream; defstream.zalloc = Z_NULL; defstream.zfree = Z_NULL; defstream.opaque = Z_NULL; // setup "a" as the input and "b" as the compressed output defstream.avail_in = (uInt)strlen(a)+1; // size of input, string + terminator defstream.next_in = (Bytef *)a; // input char array defstream.avail_out = (uInt)sizeof(b); // size of output defstream.next_out = (Bytef *)b; // output char array // the actual compression work.
๐ŸŒ
GeeksforGeeks
geeksforgeeks.org โ€บ zlib-decompresss-in-python
zlib.decompress(s) in Python - GeeksforGeeks
March 6, 2020 - # using zlib.compress(s) method t = zlib.compress(s) print("Compressed String") print(t) print("\nDecompressed String") print(zlib.decompress(t)) Output : Compressed String b'x\x9c\x0b\xc9\xc8,V\x00"w7w\x85\xc4\xd2\x92\x8c\xfc"\x1d\x85\xc4\xbc\x14\x85\xb4\xcc\xbc\xc4\x1c\x85\xca\xd4\xc4"\x85\xe2\x92\xd2\x94\xd4\xbc\x12=\x00A\xc9\x0f\x0b' Decompressed String b'This is GFG author, and final year student.' Example #2 : Python3 1=1 ยท
๐ŸŒ
GitHub
github.com โ€บ kevin-cantwell โ€บ zlib
GitHub - kevin-cantwell/zlib: A command-line utility for quickly compressing or decompressing zlib data. ยท GitHub
NAME: zlib - A wrapper for the zlib compression algorithm. USAGE: zlib [global options] command [command options] [arguments...] VERSION: 0.0.0 COMMANDS: help, h Shows a list of commands or help for one command GLOBAL OPTIONS: -d, --decompress Decompresses the input instead of compressing the output.
Starred by 48 users
Forked by 4 users
Languages ย  Go
๐ŸŒ
Jyotiprakash's Blog
blog.jyotiprakash.org โ€บ file-compression-and-decompression-in-c-using-zlib
File compression and decompression in C using ZLib
December 31, 2023 - It takes three arguments: the input ... or 'decompress'), and the output filename. ... Use the -lz flag to link against Zlib. Let's break down each step in detail. ... This command installs the Zlib development libraries and headers necessary for compiling programs that use Zlib. Here is an example program that ...
Find elsewhere
๐ŸŒ
GitHub
github.com โ€บ oliverbaileysmith โ€บ zlib-decompress
GitHub - oliverbaileysmith/zlib-decompress: Python implementation of ZLIB decompression ยท GitHub
A Python implementation of ... and returns the decompressed data. Running py main.py shows an example of compressing input data using zlib.compress and decompressing using decompress....
Author ย  oliverbaileysmith
๐ŸŒ
Pyokagan
pyokagan.name โ€บ blog โ€บ 2019-10-18-zlibinflate
Let's implement zlib.decompress()
October 18, 2019 - Bits 5: FDICT --- If set, a DICT dictionary identifier is present immediately after the FLG byte. The dictionary is a sequence of bytes which is known beforehand to both the compressor and decompressor that can be used to achieve greater compression ratios. The zlib spec does not define any preset dictionaries and leaves it up to the implementor.
๐ŸŒ
Embarcadero
docwiki.embarcadero.com โ€บ CodeExamples โ€บ Athens โ€บ en โ€บ ZLibCompressDecompress_(Delphi)
ZLibCompressDecompress (Delphi) - RAD Studio Code Examples
} LInput := TFileStream.Create(Edit1.Text, fmOpenRead); LOutput := TFileStream.Create(ChangeFileExt(Edit1.Text, 'txt'), fmCreate); LUnZip := TZDecompressionStream.Create(LInput); { Decompress data. } LOutput.CopyFrom(LUnZip, 0); { Free the streams. } LUnZip.Free; LInput.Free; LOutput.Free; end; System.SysUtils ( fr | de | ja ) System.Classes ( fr | de | ja ) System.ZLib.TZCompressionStream.Create ( fr | de | ja ) System.ZLib.TZDecompressionStream.Create ( fr | de | ja ) System.Classes.TStream.CopyFrom ( fr | de | ja ) System.Classes.TFileStream.Create ( fr | de | ja ) System.SysUtils.ChangeFileExt ( fr | de | ja ) System.ZLib.TZCompressionStream ( fr | de | ja ) System.ZLib.TZDecompressionStream ( fr | de | ja ) System.Classes.TFileStream ( fr | de | ja ) Using File Streams ยท
๐ŸŒ
Ubuntu
manpages.ubuntu.com โ€บ focal โ€บ man(3)
Ubuntu Manpage: zlib - compression and decompression operations
Creates a streaming compression or decompression command based on the mode, and return the name of the command. For a description of how that command works, see STREAMING INSTANCE COMMAND below. The following modes and options are supported: zlib stream compress ?-dictionary bindata?
๐ŸŒ
Experts Exchange
experts-exchange.com โ€บ articles โ€บ 3189 โ€บ In-Memory-Compression-and-Decompression-Using-ZLIB.html
In-Memory Compression and Decompression Using ZLIB | Experts Exchange
June 4, 2010 - You should save the original data length (before compression) and use that in preparing the last two parameters. In this simplified example, I don't provide any means to estimate the output length (Note: The zlib algorithm can get compression as high as 1000-to-1 in certain extreme cases).
๐ŸŒ
Bomberbot
bomberbot.com โ€บ python โ€บ zlib-decompression-in-python-unlocking-compressed-data
Zlib Decompression in Python: Unlocking Compressed Data - Bomberbot
July 18, 2025 - For such cases, we can leverage zlib.decompressobj() to create a decompression object that processes data incrementally. This approach is particularly useful for handling large files or real-time data streams. Here's an example demonstrating incremental decompression:
๐ŸŒ
zlib
zlib.net โ€บ manual.html
zlib 1.3.1 Manual
Depending on the size of the compression data structures selected by deflateInit or deflateInit2, a part of the dictionary may in effect be discarded, for example if the dictionary is larger than the window size in deflateInit or deflateInit2. Thus the strings most likely to be useful should be put at the end of the dictionary, not at the front. In addition, the current implementation of deflate will use at most the window size minus 262 bytes of the provided dictionary. Upon return of this function, strm->adler is set to the Adler-32 value of the dictionary; the decompressor may later use this value to determine which dictionary has been used by the compressor.
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

๐ŸŒ
Code Beautify
codebeautify.org โ€บ zlib-decompress-online
Zlib Decompress Online to Zlib Decode Text
Best ZLib Decompress Online to decode zlib text, files and urls. Easy to use Zlib Decoder Online.
๐ŸŒ
KnowledgeHut
knowledgehut.com โ€บ home โ€บ blog
KnowledgeHut Blog | Resources, Career Guides, & More
June 18, 2024 - Your go-to resource for learning and growth! KnowledgeHut blog offers insights on latest trends, Agile practices, project management tips, career guides, and more.
๐ŸŒ
SysTutorials
systutorials.com โ€บ docs โ€บ linux โ€บ man โ€บ n-zlib
zlib: compression and decompression operations - Linux Manuals (n)
Creates a streaming compression or decompression command based on the mode, and return the name of the command. For a description of how that command works, see STREAMING INSTANCE COMMAND below. The following modes and options are supported: zlib stream compress ?-dictionary bindata?