How to Install zlib on Ubuntu 26.04, 24.04 and 22.04

Last updated Tuesday, May 5, 2026 5:08 pm Joshua James 7 min read

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.

MethodPackage or SourceUpdate PathBest Fit
APT packagezlib1g-dev from Ubuntu mainUpdated with normal apt upgrade runsRecommended for nearly every C, C++, Python, Nginx, Git, or compression-related build dependency
Source buildCurrent upstream tarball from zlib.netManual rebuild or local updater scriptUse 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 sudo for 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 Releasezlib1g-dev Package Revisionpkg-config --modversion zlib
Ubuntu 26.04 LTS (resolute)1:1.3.dfsg+really1.3.1-1ubuntu31.3.1
Ubuntu 24.04 LTS (noble)1:1.3.dfsg-3.1ubuntu2.11.3
Ubuntu 22.04 LTS (jammy)1:1.2.11.dfsg-2ubuntu9.21.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 qpdf package 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

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.

Search LinuxCapable

Need another guide?

Search LinuxCapable for package installs, commands, troubleshooting, and follow-up guides related to what you just read.

Found this guide useful?

Support LinuxCapable to keep tutorials free and up to date.

Buy me a coffee Buy me a coffee

Before commenting, please review our Comments Policy.
Formatting tips for your comment

You can use basic HTML to format your comment. Useful tags currently allowed in published comments:

You type Result
<code>command</code> command
<strong>bold</strong> bold
<em>italic</em> italic
<blockquote>quote</blockquote> quote block

Got a Question or Feedback?

We read and reply to every comment - let us know how we can help or improve this guide.

Let us know you are human: