# PDF Look Scanned

> Make PDF documents look like they were scanned on a physical scanner. Applies realistic effects: grayscale conversion, Gaussian noise, slight rotation, blur, edge shadows, and random offset. Optionally extract real handwritten signatures from a source PDF (or user-provided images) and replace digital signatures on specific pages. Use when the user asks to: make a PDF look scanned, give a PDF a scanned appearance, replace digital signatures with real/handwritten ones, fake a scan, add scan effects to a document, or make a document look printed and scanned.

- Skill: `vladmdgolam/pdf-look-scanned` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add vladmdgolam/pdf-look-scanned`
- Raw SKILL.md: https://api.skillmd.com/api/skills/vladmdgolam/pdf-look-scanned/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: vladmdgolam (https://skillmd.com/u/vladmdgolam)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/vladmdgolam/pdf-look-scanned

---


# PDF Look Scanned

Make PDFs look like physical scans with optional signature replacement.

## Dependencies

```bash
pip3 install pillow pdf2image img2pdf numpy
```

Also requires `poppler` (provides `pdftoppm`):
- macOS: `brew install poppler`
- Ubuntu/Debian: `apt install poppler-utils`
- Fedora/RHEL: `dnf install poppler-utils`
- Arch: `pacman -S poppler`
- Windows: `conda install -c conda-forge poppler` or download from [poppler releases](https://github.com/osber/poppler-windows/releases)

## Quick Start

Run `scripts/make_scanned.py` for the core functionality. Read the script's `--help` for all options.

### Simple scan effect

```bash
python3 scripts/make_scanned.py document.pdf
```

### Adjust scan quality

Lower DPI and quality = grittier, more realistic cheap-scanner look:

```bash
python3 scripts/make_scanned.py document.pdf --dpi 150 --quality 75 --noise 7
```

Higher DPI = cleaner scan, larger file:

```bash
python3 scripts/make_scanned.py document.pdf --dpi 300 --quality 92
```

## Signature Replacement

### Finding signature coordinates

Before replacing signatures, determine crop and placement coordinates. All coordinates are **fractions of page dimensions** (0.0-1.0).

1. **Convert the source PDF to images** and visually inspect to find the signature region
2. **Iteratively crop** to isolate just the signature ink (no text, no table lines)
3. **On the target PDF**, find the area to clear (old digital signature) and where to paste

Use this Python snippet to explore coordinates interactively:

```python
from pdf2image import convert_from_path
from PIL import Image

pages = convert_from_path("document.pdf", dpi=200)
page = pages[0]  # 0-indexed
w, h = page.size

# Crop a region and save for inspection
crop = page.crop((int(w*0.5), int(h*0.4), int(w*0.8), int(h*0.6)))
import tempfile, os
crop.save(os.path.join(tempfile.gettempdir(), "crop_test.png"))
```

### Replace one signature

```bash
python3 scripts/make_scanned.py contract.pdf \
  --sig-pdf signatures.pdf \
  --sig-page 1 --sig-crop 0.41,0.33,0.62,0.42 \
  --sig-target 25 --sig-clear 0.61,0.41,0.85,0.52 --sig-place 0.62,0.415
```

### Replace multiple different signatures

Each set of `--sig-page`, `--sig-crop`, `--sig-target`, `--sig-clear`, `--sig-place` adds one replacement. They are matched positionally:

```bash
python3 scripts/make_scanned.py contract.pdf \
  --sig-pdf signatures.pdf \
  --sig-page 1 --sig-crop 0.41,0.33,0.62,0.42 \
  --sig-target 25 --sig-clear 0.61,0.41,0.85,0.52 --sig-place 0.62,0.415 \
  --sig-page 2 --sig-crop 0.40,0.335,0.62,0.39 \
  --sig-target 27 --sig-clear 0.61,0.635,0.85,0.72 --sig-place 0.60,0.655
```

### Signature parameters

| Parameter | Description |
|-----------|-------------|
| `--sig-pdf` | Source PDF containing real signatures |
| `--sig-page N` | Page number in source PDF (1-indexed) |
| `--sig-crop L,T,R,B` | Crop box to extract signature (fractions) |
| `--sig-target N` | Target page to replace signature on (1-indexed) |
| `--sig-clear L,T,R,B` | Area to white-out old signature (fractions) |
| `--sig-place X,Y` | Top-left position to paste new signature (fractions) |
| `--sig-size F` | Signature width as fraction of page width (default: 0.11) |
| `--sig-dpi N` | DPI for rendering source signature PDF (default: 350) |

## Scan effect parameters

| Parameter | Default | Effect |
|-----------|---------|--------|
| `--dpi` | 200 | Render resolution. Lower = grittier |
| `--quality` | 85 | JPEG compression. Lower = more artifacts |
| `--noise` | 5.0 | Gaussian noise stddev. Higher = noisier |
| `--blur` | 0.6 | Gaussian blur radius. Higher = softer |
| `--rotation` | 0.7 | Max rotation in degrees |
| `--contrast-min` | 0.88 | Min contrast (lower = more washed out) |
| `--contrast-max` | 0.95 | Max contrast |

## Workflow for signature replacement

When the user provides a PDF and a separate signature source:

1. **Check dependencies** are installed (`pillow`, `pdf2image`, `img2pdf`, `numpy`, `poppler`)
2. **Examine the source signature PDF** — convert to images, identify which pages have signatures
3. **Extract signatures** — iteratively crop to isolate the ink, verify no text bleeds in
4. **Examine the target PDF** — find pages with digital signatures, note the "Подпись:" or "Signature:" label positions
5. **Determine coordinates** — clear area must cover old signature without eating into labels; place position should be right after the label
6. **Run the script** with all parameters
7. **Verify output** — check signature pages visually, adjust coordinates if needed
8. **Check metadata** — run `exiftool` on the output to ensure no software traces remain

Common pitfalls:
- Crop box too tight: signature strokes get clipped on edges
- Clear area too wide: eats into "Подпись:"/"Signature:" labels or surrounding text
- Signature too large/small: adjust `--sig-size` (0.11 is typical for contracts)
- Source PDF is a phone photo: use higher `--sig-dpi` (350+) and higher ink threshold

