Scan documents and photos on Linux, from a GNOME app or the command line.
appscan is a small GTK4/libadwaita app and CLI for any scanner SANE supports. It started as
a way to keep an old Epson Perfection 2480 PHOTO working on a modern desktop, so it also
handles the awkward parts some models need: firmware uploads, lamp warm-up and scans that
hang. Scanning needs no root and no edits to /etc/sane.d.
- 🖥️ GNOME-style GUI: pick a scanner, source, mode, resolution, depth, brightness and contrast; preview the bed and drag to select an area.
- ⌨️ Scriptable CLI:
appscan scan out.pngwith the same settings, plus--areain millimetres and--pages Nfor multi-page PDFs. - 🎛️ Options from your scanner: the values and ranges you can choose are read from the
selected device (
scanimage -A); invalid values are rejected before scanning. - 📄 Formats: PNG, JPEG, TIFF, PNM and PDF. Each PDF page is encoded on its own: colour and grey pages as JPEG, Lineart pages as lossless 1-bit, and each page sized from its own resolution, so one PDF can mix pages scanned at different settings.
- 📚 Multi-page PDF: add pages one by one in the GUI, or with
--pages Non the command line; stopping early or a failing page still saves the pages already scanned. - 🛟 Recoverable hangs: a scan that won't cancel is killed, and scanners with a profile
are reset over USB instead of being replugged (
appscan resetdoes it on demand). - 🔌 Quirk profiles: models that need firmware, a warm-up or careful cancelling get a small built-in profile (the Epson 2480/2580 is the first).
| Model | USB ID | SANE backend | Status |
|---|---|---|---|
| Epson Perfection 2480 PHOTO | 04b8:0121 |
snapscan |
Tested (needs firmware) |
| Epson Perfection 2580 PHOTO | 04b8:0121 |
snapscan |
Untested; same USB ID and firmware as the 2480, SANE reports its film unit unsupported |
| Any other SANE-supported scanner | — | any | Generic support, untested |
Got another model working, or need a quirk for it? See Adding hardware.
curl -fsSL https://raw.githubusercontent.com/matteospanio/appscan/main/install.sh | bashThe script:
- installs the missing runtime packages with
apt(sane-utils curl p7zip-full cabextract libgtk-4-1 libadwaita-1-0); - downloads the prebuilt binary for your architecture (x86_64 or aarch64) from the latest
GitHub release into
~/.local/bin, or builds it withcargoif no binary fits; - runs
appscan setup(desktop entry, icon and man page under~/.local/share); - runs
appscan firmwareto fetch the Epson 2480/2580 firmware, unless it is already installed (only those scanners need it; setAPPSCAN_SKIP_FIRMWARE=1to skip it, and see the firmware notice below).
The prebuilt binary needs glibc 2.35, GTK 4.6 and libadwaita 1.1 or newer (Ubuntu 22.04,
Debian 12, Fedora 36 or later). The script installs packages only with apt; on other
distributions install the equivalent packages first.
A specific version:
curl -fsSL https://raw.githubusercontent.com/matteospanio/appscan/main/install.sh | APPSCAN_VERSION=0.2.0 bashUninstall (removes the binary, the desktop entry, icon, man page and ~/.local/share/appscan):
curl -fsSL https://raw.githubusercontent.com/matteospanio/appscan/main/install.sh | bash -s -- --uninstallsudo apt install libgtk-4-dev libadwaita-1-dev pkg-config build-essential \
sane-utils curl p7zip-full cabextract
cargo install --locked --git https://github.com/matteospanio/appscan # Rust 1.90 or newer
appscan setup # desktop entry, icon, man page
appscan firmware # only for the Epson 2480/2580Run appscan or open it from the applications menu. Pick a scanner, press Preview, drag
over the preview to select an area and press Scan…; the file extension chooses the
format. Use Add page and Save PDF… to build a multi-page PDF.
From the command line:
appscan list # NAME<TAB>description of each scanner
appscan scan letter.png # scanner defaults, whole bed
appscan scan -d 'snapscan:libusb:001:011' page.png # a specific scanner
appscan scan --mode Gray -r 200 --pages 4 contract.pdf # Enter between pages
appscan scan -r 600 --area 20 30 150 100 photo.jpg # LEFT TOP WIDTH HEIGHT in mm
appscan scan --brightness 30 --contrast 40 faded.png
appscan warmup # warm the lamp before a batch
appscan reset # revive a scanner that stopped answeringWithout -d, appscan uses the first scanner appscan list prints. Settings the current mode
doesn't use (for example brightness in Lineart on the Epson) are ignored. The full reference,
with more examples, is in the man page:
man appscan- Every scan runs SANE's
scanimageas a subprocess, and the available options come from parsingscanimage -Afor the selected scanner. - Why a subprocess: some backends hang inside libsane. A separate process can be killed, and a USB reset then brings the scanner back, so a hang costs a lamp warm-up instead of a replug. An in-process library call can't be interrupted that way.
- A quirk profile matches a scanner by SANE backend and USB ID. It gives appscan a private
SANE config (only that backend, so listing is fast), the firmware to install, whether the
lamp needs a warm-up (the GUI starts one at launch), and whether cancelling before image
data flows wedges the device (then appscan kills
scanimageand resets USB). - Scanners without a profile use your system SANE config as-is.
- Capture your scanner's options:
If the scanner has more than one source or mode, capturing
scanimage -L scanimage -d 'backend:device' -A > my-scanner.txt
-Awith--source/--modeset helps too. - If it works as a generic scanner, you're done: open an issue or PR to add it to the table.
- If it needs quirks, add a
Profileentry toPROFILESinsrc/profile.rswith its USB ID, SANE backend, backend.confcontents,firmware(orNone),warmupandearly_cancel_wedges. - Save the
-Acapture undertests/fixtures/and add a parser test for it insrc/sane.rs. - Open a pull request with what you tested.
Warning
The Epson Perfection 2480/2580 firmware (esfw41.bin) is proprietary software
© Seiko Epson Corporation.
- appscan does not include or redistribute it.
- It is downloaded from Epson's own server (
ftp.epson.com, inside the Epson Scan driver for Windows) only whenappscan firmwareruns, which the install script does unlessAPPSCAN_SKIP_FIRMWARE=1is set. It is then extracted and SHA-256 verified locally. - It is intended only for use with an Epson scanner you own. You are responsible for complying with Epson's license terms; appscan's MIT license does not cover it.
- appscan is not affiliated with, authorized by or endorsed by Seiko Epson Corporation. Epson, Perfection and other product names are trademarks of their respective owners.
sudo apt install libgtk-4-dev libadwaita-1-dev pkg-config build-essential sane-utils
cargo build
cargo test
cargo clippy --all-targets -- -D warnings
cargo run -- scan test.png -r 150MIT © 2026 Matteo Spanio
This software is based in part on the work of the Independent JPEG Group (JPEG encoding via the jpeg-encoder crate).
