You plug in a scanner and nothing happens
You connect a scanner to your Fedora machine. The power LED blinks. You open your document viewer. Nothing appears. The system sees a new USB device, but your scanning software refuses to acknowledge it. This happens because Fedora does not ship every proprietary scanner driver by default. You need to tell the system which backend to load, grant your user access to the USB bus, and optionally open a network port if you plan to share the device across your local network.
What SANE actually does
SANE stands for Scanner Access Now Easy. It is a unified interface that sits between your scanning application and the hardware. Think of it like a universal translator. The application speaks a standard protocol. The hardware speaks a manufacturer-specific dialect. SANE translates between them. Each scanner model requires a specific backend module. Without the correct module, the kernel sees a USB device, but the scanning stack has no idea how to talk to it.
The backend lives in user space. It communicates with the device through /dev/bus/usb/ or /dev/sg* nodes. The kernel handles the low-level USB enumeration. SANE handles the device-specific commands. If the backend is missing, or if your user lacks read/write permissions on those nodes, the scan fails silently or throws a permission denied error. Fedora splits the SANE stack into a core package and modular driver packages. Installing the generic package alone often leaves you without the actual scanner support.
Install the right backend and verify detection
Start by identifying the hardware. The kernel logs every USB connection. You can query the active devices to find the vendor and product ID. This ID tells you which SANE backend package to install. Fedora's package manager groups scanner drivers under a metapackage that pulls in the most common backends. You can also install the full driver collection if you want to avoid guessing.
Here's how to identify the device and install the required packages.
# List USB devices to find the scanner vendor and product ID
lsusb | grep -i scanner
# Install the core SANE stack, common scanner drivers, and a CLI test tool
sudo dnf install sane-backends sane-backends-drivers-scanners xsane
# Query the SANE stack to see if it recognizes the newly installed backend
scanimage -L
The scanimage -L command asks the SANE library to probe all loaded backends. If the output lists your device with a URI like hpaio:/net/... or genesys:libusb:..., the backend is active. If the command returns nothing, the driver package is missing or the kernel has not exposed the device node yet. Unplug and replug the scanner to trigger a fresh udev event.
Handle permissions and SELinux
Fedora enforces strict access controls. The scanner group exists specifically to grant non-root users access to USB scanning devices. If your user is not in that group, the backend process cannot open the device node. SELinux adds another layer. It labels every file and process. If a device node has an incorrect label, the kernel blocks access before the backend even runs. You do not need to disable SELinux. You just need to restore the correct context and let the policy module handle the rest.
Here's how to assign the correct group and fix any labeling issues.
# Add your current user to the scanner group for USB device access
sudo usermod -aG scanner $USER
# Restore default SELinux contexts on the USB bus directory
sudo restorecon -Rv /dev/bus/usb/
# Restart the SANE daemon to pick up the new group membership and labels
sudo systemctl restart saned
# Re-run the device probe to confirm detection
scanimage -L
Log out and log back in after changing groups. Group memberships are evaluated at login time. The shell session will not inherit the new group until you reauthenticate. SELinux denials show up in journalctl -t setroubleshoot with a one-line summary. Read those before disabling SELinux. The audit trail will tell you exactly which process was blocked and which file context was wrong.
Open the firewall for network scanning
Local scanning does not require network access. The backend talks directly to the USB device through the kernel. Network scanning requires the saned daemon and an open TCP port. Fedora's firewall tracks runtime and persistent configurations separately. You must reload the firewall after every permanent rule change. Otherwise the runtime configuration and the persistent configuration diverge.
Here's how to enable the daemon and open the required port.
# Enable the SANE network daemon and start it immediately
sudo systemctl enable --now saned
# Add the SANE port to the persistent firewall configuration
sudo firewall-cmd --permanent --add-port=6566/tcp
# Apply the persistent rule to the active firewall runtime
sudo firewall-cmd --reload
# Verify the port is open and listening on the expected interface
ss -tlnp | grep 6566
The saned service reads its configuration from /etc/sane.d/saned.conf. Files in /etc/ are user-modified. Files in /usr/lib/ ship with the package. Edit /etc/. Never edit /usr/lib/. The default configuration restricts access to the local network. You can add specific IP ranges if you run a multi-subnet setup. Run firewall-cmd --reload after every rule change. Trust the package manager. Manual file edits drift, snapshots stay.
Verify it worked
Run a test scan to a temporary file. The command forces the backend to initialize the hardware, read the sensor data, and write a raw image. If the backend is misconfigured, the command will hang or return a hard error.
# Replace the device URI with the exact string from scanimage -L
scanimage -d "hpaio:/net/YourScannerName" --format=png > /tmp/test-scan.png
# Check the file size to confirm data was actually written
ls -lh /tmp/test-scan.png
# Open the file in your default image viewer to verify quality
xdg-open /tmp/test-scan.png
If the file is zero bytes, the backend failed to communicate with the sensor. If the file contains only black or white pixels, the scanner lid was closed or the glass was dirty. Clean the platen and run the command again. Reboot before you debug. Half the time the symptom is gone.
Common pitfalls and what the error looks like
The scanimage command will refuse to proceed and print scanimage: open of device hpaio:/net/... failed: Invalid argument. The invalid argument usually means the backend URI does not match the actual device path. Copy the URI exactly as scanimage -L prints it. Do not guess the network name.
If you see Permission denied when running the scan command, your user is not in the scanner group or the SELinux context is still wrong. Run getenforce to confirm SELinux is in enforcing mode. Check /var/log/audit/audit.log for AVC denials using ausearch -m avc -ts recent | grep scanner. The output will show the exact source process and the denied operation. Apply the correct policy module if the default one is missing.
Network scans fail with Connection refused when the saned service is not running or the firewall is blocking port 6566. Run systemctl status saned to check the service state. The status command shows recent log lines AND state in one view. Always check status before restart. If the service is dead, look at journalctl -xeu saned for the crash reason. The x flag adds explanatory text and the e flag jumps to the end. Most sysadmins type journalctl -xeu <unit> muscle-memory style.
Choose your scanning workflow
Use scanimage when you need a quick CLI test or script automation. Use simple-scan when you want a straightforward GUI for documents and photos. Use xsane when you need advanced color correction and batch processing. Use gscan2pdf when you are scanning multi-page documents directly into PDF format. Stay on the upstream Workstation defaults if you only deviate from the configuration occasionally.