Portable, self-contained PDF compressor. A single executable with Ghostscript (statically linked) embedded inside: copy it to any Linux server or Apple Silicon Mac and it works — no installation and no extra files required.
./pdfcompress input.pdfProduces input-compressed.pdf in the same folder, using the ebook profile.
./pdfcompress input.pdf [output.pdf] [profile]| Argument | Required | Description |
|---|---|---|
input.pdf |
Yes | Source PDF to compress. |
output.pdf |
No | Output path. Defaults to <input>-compressed.pdf. |
profile |
No | Compression level. Defaults to ebook. |
| Profile | Resolution | Recommended use |
|---|---|---|
screen |
72 dpi | Smallest size (screen, web, email). |
ebook |
150 dpi | Default. Good balance. |
printer |
300 dpi | Quality printing. |
prepress |
300 dpi | Highest quality (prepress). |
# Default compression (ebook)
./pdfcompress raw.pdf
# Specifying the output file
./pdfcompress raw.pdf result.pdf
# Maximum compression for email
./pdfcompress raw.pdf light.pdf screen
# High quality for printing
./pdfcompress report.pdf report-print.pdf printerThe repository ships dummy.pdf so you can check any build straight away
without looking for a PDF first: 5 pages of text with two embedded TrueType
fonts, 881 KB (that weight is mostly the fonts — there are no images).
./pdfcompress dummy.pdfCompressing PDF...
Input: dummy.pdf
Profile: ebook
Ghostscript: embedded (10.04.0)
PDF compressed successfully.
Original: 881107 bytes
Compressed: 74083 bytes
Reduction: 91.59%
Output: ./dummy-compressed.pdf
Reference results (Ghostscript 10.04.0):
| Profile | Original | Compressed | Reduction |
|---|---|---|---|
ebook |
881,107 B | 74,083 B | 91.59 % |
screen |
881,107 B | 74,119 B | 91.59 % |
The darwin-arm64 build reproduces both figures. The output is not
byte-identical between runs, though: Ghostscript stamps CreationDate, ModDate
and a document ID into the PDF, so two runs over the same input differ in a few
dozen bytes and the total size can drift by a couple of bytes.
screen does not beat ebook here because the sample has no images to
downsample: the gain comes from re-encoding the embedded fonts and streams, so
both profiles converge. Use a scanned/image-heavy PDF to see the profiles apart.
dummy.pdf is the only PDF tracked in the repository; every generated output
(*-compressed.pdf and any other local .pdf) is git-ignored.
Each release ships one executable per platform on the Releases page. Pick the one matching your machine — that single file is all you need:
| Asset | For |
|---|---|
pdfcompress-linux-x86_64 |
Intel/AMD Linux servers (uname -s -m → Linux x86_64) |
pdfcompress-linux-arm64 |
ARM64 Linux: Graviton, Ampere, linux/arm64 containers on Apple Silicon (uname -s -m → Linux aarch64) |
pdfcompress-darwin-arm64 |
Apple Silicon Macs, M1 onwards (uname -s -m → Darwin arm64) |
The assets are split by OS and CPU architecture, not by distribution. The Linux
builds are statically linked, so the host's libc is irrelevant: the same
pdfcompress-linux-* runs on glibc distributions (Debian, Ubuntu, RHEL) and on
musl ones (Alpine) alike. Alpine only needs bash installed, which the launcher's
shebang requires and busybox does not provide. CI verifies this on every build by
running the freshly built Linux binary inside an alpine:3 container.
# Download (adjust the URL to the release and platform you want)
curl -sL -o pdfcompress <release-asset-url>
chmod +x pdfcompress
./pdfcompress document.pdfRunning the wrong asset is not silent — the launcher checks both the OS and the
architecture on startup and tells you which one to download instead. Checking the
architecture alone would not be enough: an Apple Silicon Mac reports arm64 just
like an ARM Linux server, but it cannot run the Linux binary.
To make it available from any path:
sudo mv pdfcompress /usr/local/bin/
pdfcompress document.pdfThe binary is not committed to the repository; it is built by build.sh and
published to Releases. To build it yourself:
./build.sh # embeds Ghostscript 10.04.0 by default
./build.sh 10.04.0 # or pin a specific versionRequirements:
- Linux:
gcc,make,curland a static glibc —sudo apt-get install build-essential libc6-devon Debian/Ubuntu. - macOS: the Xcode Command Line Tools (
xcode-select --install). Nothing from Homebrew:build.shdeliberately builds with an emptyPKG_CONFIG_PATHand fails if the result links against anything outside/usr/liband/System/Library, which would make the binary non-portable.
Ghostscript is compiled natively, so build.sh always produces a binary for the
machine it runs on (it refuses to run on an unsupported platform). To get the
macOS executable, build on a Mac — which is exactly what the release workflow
does, one runner per platform.
See TECHNOLOGY.md for the full details of how the binary is
built and why.
pdfcompress is a shell script with a gzip-compressed Ghostscript binary
appended at the end. On first run it extracts that binary to a temporary cache
and reuses it on subsequent runs:
/tmp/.pdfcompress-<hash>/gs
The cache is keyed by the binary's hash, so extraction only happens once. You can delete that directory safely; it will be regenerated automatically.
| Code | Meaning |
|---|---|
0 |
PDF compressed successfully. |
1 |
Usage or runtime error (arguments, file, etc.). |
2 |
The result was not smaller than the original. |
- Linux on x86_64 or arm64, or macOS on Apple Silicon, matching the asset you downloaded. Any Linux distribution: the build is static, so glibc and musl systems are equally fine.
- Standard utilities:
bash,gzip/gunzip,awk,tail,wc— present by default on any Linux distribution and on macOS alike. On minimal container images such as Alpine,bashis the one that is usually missing (apk add bash); busyboxashdoes not satisfy the launcher's shebang.
Download pdfcompress-darwin-arm64 and run it directly; it needs no Docker, no
VM and no Ghostscript installed:
chmod +x pdfcompress-darwin-arm64
./pdfcompress-darwin-arm64 document.pdfmacOS runs Mach-O binaries, so a linux-* asset will not work there whatever the
architecture says — the launcher stops with a message pointing at the right one.
If macOS has flagged the download as quarantined and Gatekeeper complains, clear the flag once:
xattr -d com.apple.quarantine pdfcompress-darwin-arm64Both linux-* assets run unmodified inside containers, including musl-based ones.
On Alpine the only prerequisite is bash:
RUN apk add --no-cache bash
COPY pdfcompress-linux-arm64 /usr/local/bin/pdfcompress
RUN chmod +x /usr/local/bin/pdfcompressPick the asset by the container's architecture, not the host's: a linux/arm64
image on an Apple Silicon Mac needs pdfcompress-linux-arm64, even though the
same machine would need pdfcompress-darwin-arm64 outside Docker.
Intel Macs and 32-bit targets are not published, but the build supports any
platform it can compile on natively: add the target to the matrix in
.github/workflows/release.yml with a runner of
that platform, or run ./build.sh on the machine itself.
pdfcompress embeds Ghostscript and is distributed under the AGPL-3.0
license. See LICENSE and NOTICE.md for details and
practical implications.