Build failures that mention zlib.h, -lz, or a missing zlib library usually mean Ubuntu has the runtime library but not the development headers. To install zlib on Ubuntu for compiling software, use the zlib1g-dev package from Ubuntu’s main repository; it provides the headers, static library, shared-library symlinks, and pkg-config metadata most build systems expect.
The package names matter here. Ubuntu uses zlib1g for the runtime library and zlib1g-dev for development files; names such as zlib-dev, zlib-devel, libz-dev, and python3-zlib are not the Ubuntu development-header package. Source builds are still useful when you need the current upstream zlib release instead of the packaged version in Ubuntu 26.04 LTS (resolute), 24.04 LTS (noble), or 22.04 LTS (jammy).
Install zlib on Ubuntu
Most users should install zlib1g-dev with APT because it receives normal Ubuntu package updates and integrates cleanly with other development packages. Compile from source only when a project specifically needs the latest upstream zlib release, custom compiler flags, or an isolated library prefix under /usr/local/zlib.
| Method | Package or Source | Update Path | Best Fit |
|---|---|---|---|
| APT package | zlib1g-dev from Ubuntu main | Updated with normal apt upgrade runs | Recommended for nearly every C, C++, Python, Nginx, Git, or compression-related build dependency |
| Source build | Current upstream tarball from zlib.net | Manual rebuild or local updater script | Use when you need the latest upstream zlib release or custom build flags outside Ubuntu’s package database |
The APT package names and source-build workflow work on Ubuntu 26.04 LTS (resolute), 24.04 LTS (noble), and 22.04 LTS (jammy). The packaged zlib version differs by release, so use the verification table after installation when exact version output matters.
Quick zlib Install Command for Ubuntu
Start by refreshing your local package metadata:
sudo apt update
These commands use
sudofor package-management tasks that need root privileges. If your account is not configured for sudo yet, follow the guide on adding a user to sudoers on Ubuntu before continuing.
Install the zlib development package and pkg-config so build systems can detect the library cleanly:
sudo apt install zlib1g-dev pkg-config
The zlib1g-dev package pulls in the runtime library if it is not already installed. pkg-config is not zlib itself, but many build scripts use it to discover compiler and linker flags.
Older apt-get install syntax targets the same zlib1g-dev and pkg-config packages. This article uses apt for clearer interactive output.
Check Whether zlib Development Files Are Installed
On Ubuntu, package-manager state is the most reliable installed-state check. This query uses the grep command to return a line only when zlib1g-dev is installed and configured:
dpkg -l zlib1g-dev | grep '^ii'
Relevant output on Ubuntu 26.04 looks like this:
ii zlib1g-dev:amd64 1:1.3.dfsg+really1.3.1-1ubuntu3 amd64 compression library - development
No output means the development headers are not installed yet. Install zlib1g-dev before retrying a build that needs zlib.h or links with -lz.
Verify zlib with pkg-config
After installation, verify that development metadata is visible:
pkg-config --modversion zlib
The command prints the zlib library version exposed by the installed development package. Current Ubuntu package results are:
| Ubuntu Release | zlib1g-dev Package Revision | pkg-config --modversion zlib |
|---|---|---|
| Ubuntu 26.04 LTS (resolute) | 1:1.3.dfsg+really1.3.1-1ubuntu3 | 1.3.1 |
| Ubuntu 24.04 LTS (noble) | 1:1.3.dfsg-3.1ubuntu2.1 | 1.3 |
| Ubuntu 22.04 LTS (jammy) | 1:1.2.11.dfsg-2ubuntu9.2 | 1.2.11 |
If pkg-config reports that zlib was not found, reinstall the development package and metadata tool:
sudo apt install --reinstall zlib1g-dev pkg-config
Compile zlib from Source on Ubuntu
Source compilation installs a separate upstream zlib build under /usr/local/zlib. Keep the APT package for normal system builds unless you intentionally want this custom prefix to take priority for specific software you compile yourself.
Install the compiler, download tools, Python JSON parser, certificate bundle, and pkg-config:
sudo apt install build-essential curl ca-certificates python3 pkg-config
The GCC compiler on Ubuntu comes through the build-essential package. The curl command retrieves release metadata and the official source archive.
Download the current upstream release. These commands use the GitHub release API only to read the latest tag, then download the matching official tarball from zlib.net:
mkdir -p "$HOME/zlib-source-build"
cd "$HOME/zlib-source-build"
ZLIB_VERSION=$(curl -fsSL https://api.github.com/repos/madler/zlib/releases/latest | python3 -c 'import json, sys; tag=json.load(sys.stdin).get("tag_name", "").removeprefix("v"); print(tag)')
if [ -z "$ZLIB_VERSION" ]; then
echo "Could not detect the latest zlib release."
exit 1
fi
printf 'Latest zlib release: %s\n' "$ZLIB_VERSION"
curl -fL -o "zlib-${ZLIB_VERSION}.tar.gz" "https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz"
The command prints the release it resolved before downloading the archive. The example below uses version-pattern notation because the latest patch release can change:
Latest zlib release: 1.3.x
Remove any stale extracted tree for the same release, then extract the archive and enter the source tree. The tar command handles the gzip-compressed source archive:
rm -rf "zlib-${ZLIB_VERSION}"
tar -xzf "zlib-${ZLIB_VERSION}.tar.gz"
cd "zlib-${ZLIB_VERSION}"
Configure the build with a dedicated prefix so the custom library stays separate from Ubuntu-managed files:
./configure --prefix=/usr/local/zlib
Relevant configure output should show compiler and shared-library support:
Checking for gcc... Checking for shared library support... Checking for size_t... Yes. Checking for off64_t... Yes.
Build zlib, then run the upstream test suite before installing:
make -j"$(nproc)"
make test
The final test lines should end with successful shared and 64-bit checks. The version line, if shown earlier in your terminal, should match the release you downloaded:
*** zlib shared test OK ***
*** zlib 64-bit test OK ***
Install the compiled library and register the custom library path with the dynamic linker:
sudo make install
printf '%s\n' '/usr/local/zlib/lib' | sudo tee /etc/ld.so.conf.d/zlib-custom.conf
sudo ldconfig
Verify that the custom build is visible through pkg-config and the linker cache:
PKG_CONFIG_PATH=/usr/local/zlib/lib/pkgconfig pkg-config --modversion zlib
ldconfig -p | grep '/usr/local/zlib/lib/libz.so'
Relevant output includes the resolved zlib version and linker-cache paths under /usr/local/zlib. The example below uses version-pattern notation because the source release can advance:
1.3.x libz.so.1 (libc6,x86-64) => /usr/local/zlib/lib/libz.so.1 libz.so (libc6,x86-64) => /usr/local/zlib/lib/libz.so
When compiling another project against this custom zlib build, pass the custom metadata path for that build only:
PKG_CONFIG_PATH=/usr/local/zlib/lib/pkgconfig ./configure
That one-command environment assignment keeps the custom source build intentional. It avoids permanently changing your shell profile and accidentally steering unrelated builds away from Ubuntu’s packaged zlib.
Update Source-Compiled zlib on Ubuntu
APT handles updates for zlib1g-dev. Source-compiled zlib needs a rebuild when upstream publishes a new release, so create a small updater in /usr/local/bin:
sudo tee /usr/local/bin/update-zlib-source > /dev/null <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
PREFIX="/usr/local/zlib"
CONF="/etc/ld.so.conf.d/zlib-custom.conf"
CACHE_PARENT="${XDG_CACHE_HOME:-$HOME/.cache}/zlib-source-updater"
mkdir -p "$CACHE_PARENT"
WORKDIR=$(mktemp -d "$CACHE_PARENT/build.XXXXXX")
cleanup() {
rm -rf "$WORKDIR"
}
trap cleanup EXIT
echo "Checking latest zlib release..."
LATEST=$(curl -fsSL https://api.github.com/repos/madler/zlib/releases/latest | python3 -c 'import json, sys; tag=json.load(sys.stdin).get("tag_name", "").removeprefix("v"); print(tag)')
if [ -z "$LATEST" ]; then
echo "Could not detect the latest zlib release."
exit 1
fi
CURRENT="not installed"
if [ -f "$PREFIX/lib/pkgconfig/zlib.pc" ]; then
CURRENT=$(PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig" pkg-config --modversion zlib)
fi
echo "Current installed version: $CURRENT"
echo "Latest available version: $LATEST"
if [ "$CURRENT" = "$LATEST" ]; then
echo "Already running the latest version. No update needed."
exit 0
fi
read -r -p "Continue with update? [y/N] " REPLY
case "$REPLY" in
[Yy]|[Yy][Ee][Ss]) ;;
*) echo "Update cancelled."; exit 0 ;;
esac
cd "$WORKDIR"
echo "Downloading zlib ${LATEST}..."
curl -fL -o "zlib-${LATEST}.tar.gz" "https://zlib.net/zlib-${LATEST}.tar.gz"
tar -xzf "zlib-${LATEST}.tar.gz"
cd "zlib-${LATEST}"
./configure --prefix="$PREFIX"
make -j"$(nproc)"
make test
BACKUP=""
if [ -d "$PREFIX" ]; then
BACKUP="${PREFIX}.backup.$(date +%Y%m%d%H%M%S)"
sudo mv "$PREFIX" "$BACKUP"
fi
if sudo make install; then
printf '%s\n' "$PREFIX/lib" | sudo tee "$CONF"
sudo ldconfig
else
sudo rm -rf "$PREFIX"
if [ -n "$BACKUP" ]; then
sudo mv "$BACKUP" "$PREFIX"
sudo ldconfig
fi
echo "Update failed; restored the previous installation if a backup existed."
exit 1
fi
if [ -n "$BACKUP" ]; then
echo "Previous installation saved at $BACKUP. Remove it after confirming dependent builds work."
fi
echo "Update complete. New version: $(PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig" pkg-config --modversion zlib)"
EOF
sudo chmod 0755 /usr/local/bin/update-zlib-source
Run the updater whenever you want to check for a newer upstream release:
update-zlib-source
When the installed source build is already current, the updater exits without rebuilding. The example below uses version-pattern notation because the current upstream patch release can change:
Checking latest zlib release... Current installed version: 1.3.x Latest available version: 1.3.x Already running the latest version. No update needed.
If an update proceeds, the script moves the previous /usr/local/zlib directory to a timestamped backup before installing the new build. Keep that backup until the software that depends on the custom library has been rebuilt or tested.
Troubleshoot zlib on Ubuntu
Fix zlib.h Missing Header Errors
The error fatal error: zlib.h: No such file or directory means the compiler cannot find the zlib development headers. Install zlib1g-dev, then confirm the header exists:
sudo apt install zlib1g-dev
Confirm that the header is now available:
dpkg -L zlib1g-dev | grep '/zlib.h$'
/usr/include/zlib.h
The runtime package zlib1g is not enough for compilation. It lets already-built applications run, while zlib1g-dev supplies zlib.h, zconf.h, libz.a, and the development symlinks used during builds.
Fix configure: error: zlib library not found
Autotools and CMake projects usually raise this error when the development package or pkg-config metadata is missing. For Ubuntu packages, reinstall both pieces:
sudo apt install --reinstall zlib1g-dev pkg-config
Then confirm the linker flag resolves:
pkg-config --libs zlib
-lz
For a source build under /usr/local/zlib, pass the custom metadata path when running the dependent project’s configure step:
PKG_CONFIG_PATH=/usr/local/zlib/lib/pkgconfig ./configure
Use the Correct Ubuntu Package Name
On Ubuntu, sudo apt install zlib1g-dev is the development-header command. If you searched for libz, that is the linker/library name rather than the package to install. zlib-devel is a Red Hat-family package name, zlib-dev is not an Ubuntu package, libz-dev has no Ubuntu candidate in the supported LTS releases, and python3-zlib is not needed for normal Python because Python’s zlib module is already available with the interpreter.
python3 -c "import zlib; print(zlib.ZLIB_VERSION)"
The Python command prints the zlib library version Python is using, such as 1.3.1 on Ubuntu 26.04, 1.3 on Ubuntu 24.04, or 1.2.11 on Ubuntu 22.04.
Install zlib-flate on Ubuntu
The zlib-flate command is not installed by zlib1g-dev. Ubuntu ships that utility in the qpdf package from Universe, so install qpdf if you need the standalone compression and decompression helper:
sudo apt install qpdf
Verify that the helper command is present:
command -v zlib-flate
/usr/bin/zlib-flate
The
qpdfpackage is in Ubuntu’s Universe component. If a minimal or customized system cannot locate it, enable the component with the guide on Universe and Multiverse repositories on Ubuntu, then rerun the install command.
Check Which zlib a Custom Application Loads
If you have both Ubuntu’s packaged zlib and a source build under /usr/local/zlib, check the final application binary instead of guessing which library it loads:
ldd /path/to/application | grep libz
A path under /usr/local/zlib/lib means the custom build is active for that binary. A path under /lib or /usr/lib means the application is using Ubuntu’s packaged runtime library.
Remove zlib from Ubuntu
Remove only the install path you used. Do not remove the zlib1g runtime package on a normal Ubuntu system because many core packages and desktop applications depend on it.
Remove APT-Installed zlib Development Files
Remove the development headers with APT:
sudo apt remove zlib1g-dev
If you installed pkg-config only for this zlib task and do not need it for other development packages, remove it separately:
sudo apt remove pkg-config
Preview orphaned cleanup before running it:
sudo apt autoremove --dry-run
Only continue if the preview contains packages you genuinely no longer need:
sudo apt autoremove
Verify that the development package is gone. No output means zlib1g-dev is no longer installed:
dpkg -l zlib1g-dev | grep '^ii'
The runtime library should still be present:
dpkg -l zlib1g | grep '^ii'
Remove Source-Compiled zlib
These commands permanently delete the custom zlib build under
/usr/local/zlib. Rebuild or reconfigure any application that depends on that exact prefix before removing it.
sudo rm -rf /usr/local/zlib
sudo rm -f /etc/ld.so.conf.d/zlib-custom.conf
sudo rm -f /usr/local/bin/update-zlib-source
sudo ldconfig
If you used the manual source-build workspace from this article and no longer need the downloaded archive or extracted source tree, remove that user-owned build directory separately:
rm -rf "$HOME/zlib-source-build"
If the updater created a timestamped backup during a previous source update, remove it only after confirming you no longer need that older build:
ls -d /usr/local/zlib.backup.*
Delete the specific backup directory you no longer need, replacing the path with the exact directory shown on your system:
sudo rm -rf /usr/local/zlib.backup.YYYYMMDDHHMMSS
Confirm the custom linker path is no longer registered:
ldconfig -p | grep '/usr/local/zlib/lib/libz.so'
No output means the custom zlib path has been removed from the linker cache.
zlib Resources for Ubuntu
- zlib official website publishes the current release tarballs, signatures, and project notes.
- zlib manual documents the C API for applications that call zlib directly.
- zlib how-to examples show common compression and decompression patterns.
- zlib GitHub releases provide release notes and machine-readable latest-release metadata.
Conclusion
zlib development files are available on Ubuntu through zlib1g-dev, with source-built zlib available under /usr/local/zlib when a project needs the latest upstream release. From here, the same build stack pairs naturally with GCC on Ubuntu or larger source workflows such as building Nginx from source on Ubuntu.
Formatting tips for your comment
You can use basic HTML to format your comment. Useful tags currently allowed in published comments:
<code>command</code>command<strong>bold</strong><em>italic</em><blockquote>quote</blockquote>