Show HN: Make PDFs look scanned (CLI or in the browser via WASM)
Summary
A CLI and browser-based tool that converts PDFs into image-only PDFs with simulated scan effects like skew, grayscale, noise, and JPEG artifacts, using Go and WebAssembly.
View Cached Full Text
Cached at: 06/20/26, 08:17 PM
overflowy/make-look-scanned
Source: https://github.com/overflowy/make-look-scanned
make-look-scanned
A CLI that takes a PDF and degrades it to look like a physical scan of a printout — skew, grayscale, warm paper tone, scanner grain, defocus, edge shadow, and JPEG compression artifacts. Also runs client-side in the browser via WASM.
Each page is rasterized to an image, run through the effect pipeline, and reassembled into a new image-only PDF (the original selectable text is gone — faithful to a basic scanner).
Build
Requires Go and a C toolchain (go-fitz links MuPDF via cgo, so the binary is self-contained — nothing to install at runtime).
go build -o make-look-scanned .
Usage
make-look-scanned [flags] input.pdf
Flags may appear before or after the input filename.
make-look-scanned in.pdf # -> in.scanned.pdf
make-look-scanned in.pdf -o out.pdf
make-look-scanned in.pdf --noise 0.4 --skew 2.5 --jpeg-quality 30
Flags
| Flag | Default | Meaning |
|---|---|---|
-o | <input>.scanned.pdf | output path |
--preset | — | named preset from config.toml |
--seed | content hash | random seed (override for a new look) |
--force | false | overwrite an existing output file |
--dpi | 150 | render resolution |
--skew | 0.6 | max rotation degrees (0 disables) |
--grayscale | true | desaturate (--grayscale=false keeps color) |
--paper-tone | 0.6 | warm paper tint strength 0..1 |
--noise | 0.08 | scanner grain 0..1 |
--blur | 0.4 | defocus gaussian sigma |
--edge-shadow | 0.15 | border vignette 0..1 |
--jpeg-quality | 70 | JPEG quality 1..100 |
Each numeric knob disables its effect at 0.
Determinism
Output is deterministic by default: the seed is derived from the input
PDF’s content, so the same file always produces the same scan. Pass --seed N
for a different (but reproducible) look. Same input + seed yields a
byte-identical PDF.
Presets
Define reusable bundles in
$XDG_CONFIG_HOME/make-look-scanned/config.toml (falls back to
~/.make-look-scanned/config.toml when XDG_CONFIG_HOME is unset). Keys
mirror the flag names with underscores:
[presets.medium]
skew = 1.5
paper_tone = 0.6
noise = 0.2
blur = 0.6
edge_shadow = 0.3
jpeg_quality = 45
make-look-scanned --preset medium in.pdf
Precedence: built-in defaults → selected preset → explicit CLI flags (flags always win).
Browser (WebAssembly)
The effect pipeline also runs in the browser. go-fitz/MuPDF can’t compile to wasm, so the browser uses PDF.js to rasterize pages and hands the pixels to the same Go effects + assembly code compiled to wasm.
Dev (needs network for the PDF.js CDN):
./web/build.sh # builds web/main.wasm + wasm_exec.js
(cd web && python3 -m http.server 8080) # then open http://localhost:8080
Single self-contained file (works offline, nothing to serve):
task build:web # writes dist/make-look-scanned.html (~8 MB)
dist/make-look-scanned.html inlines the wasm, Go’s runtime glue, and PDF.js
(library + worker) as base64 — open it directly in a browser. Output is
visually equivalent to the CLI but not byte-identical, since PDF.js and MuPDF
rasterize differently.
License
AGPL-3.0. The CLI statically links MuPDF (via go-fitz), which is AGPL-3.0, so the combined binary is AGPL-3.0 — distributing it requires offering the corresponding source. The browser build does not include MuPDF (it uses PDF.js, Apache-2.0).
Similar Articles
Show HN: A graph paper generator that renders vector PDFs in the browser
A free browser-based graph paper generator that lets users create and download custom grid PDFs without login or watermark.
Show HN: I built 184 free browser tools – PDF, image, dev, AI tasks, no upload
Brevio provides 184 free browser-based tools for PDF, image, development, and AI tasks, all without requiring uploads or signup.
Show HN: Firefox in WebAssembly
Firefox is compiled to run in WebAssembly, using WebGL-based rendering and an experimental JS-to-WASM JIT, with web content proxied through a Puter-hosted Wisp server.
Show HN: Inkwash, a watercolor sketching app and explanation
Inkwash is a WebGL2-based watercolor sketching app that simulates pigment flow and paper interaction, generated with Claude Fable 5. The article explains the technical pipeline of floating-point textures and shaders behind the realistic watercolor effect.
The surprisingly complex journey to text-selectable client-side generated PDFs
This article explores the technical challenges of generating text-selectable PDFs on the client side, introducing SDocs as a solution and providing installation instructions for its CLI tool.