ScanLink is a robust, lightweight system-tray application that bridges the gap between local TWAIN-compatible scanners and secured web applications. It allows web apps running in containers or remote servers to interact with physical scanning hardware connected to the client machine via a secure local API.
- 🔒 Secure HTTPS API
Exposes a secure endpoint (https://localhost:5443/scan) with auto-generated SSL certificates. - 🔗 Deep Link Support
Trigger scans directly from browser links usingscanlink://scan?docId=123. - 📡 Polling-Friendly Status API
Track scan status, page count, completion, and errors through REST endpoints. - 📄 Instant PDF Generation
Automatically converts physical documents into optimized, multi-page PDFs ready for upload. - ⚙️ Configurable Quality
Adjustable source, side, color, and resolution settings to balance quality and file size. - 🗜️ Smart Compression
Built-in JPEG compression ensures file sizes remain small (<500KB/page) without sacrificing readability. - 🔌 Plug-and-Play
Works with any TWAIN-compatible scanner (Canon, HP, Fujitsu, Epson, etc.). - 🚀 System Tray Integration
Runs silently in the background with quick access to settings and startup management. - 🛡️ Secure Isolation
Restricted to localhost access only, ensuring no external network exposure. - 💾 Configuration Persistence
Remembers your default scanner and scan profile settings.
- Python 3.10+: Core logic and runtime.
- Flask: Local REST API server for scan requests, status polling, and PDF retrieval.
- PyTwain: Low-level interface for TWAIN driver communication.
- Pillow (PIL): Advanced image processing and compression.
- ReportLab: Professional PDF generation engine.
- PyStray: System tray icon and menu integration.
- Tkinter: Native GUI dialogs for scanner selection.
- cryptography + Windows CryptoAPI/DPAPI: Generate a localhost identity, trust its server certificate for the current user, and protect its private key.
- PyInstaller: Compilation into standalone Windows executable.
- Inno Setup: Professional Windows installer generation.
- Download and run
ScanLinkSetup.exe. - Follow the installation wizard (installs to your Windows user profile).
- Launch ScanLink from your Start Menu or Desktop.
- The app appears in your system tray and sets up its secure connection automatically. Approve any Windows or browser prompt, then scan from your application. No commands or certificate imports are needed.
If Windows blocks setup, ScanLink offers Retry. You can also right-click its tray icon and choose Retry secure connection setup. If your organization manages this computer and setup stays blocked, contact your support team.
- Unzip the release package.
- Run
ScanLink.exedirectly.
- Install Python 3.10+.
- Install dependencies:
pip install -r requirements.txt. - Run the app:
python main.py.
- Start the App: Ensure the ScanLink icon is visible in your system tray.
- Confirm Scan Profile: Right-click the tray icon and confirm the archive-safe defaults: Source → ADF, Side → Front, Color → Color, Resolution → 200 DPI, and Paper Protection unchecked.
- Trigger Scan:
- Click the "Scan" button in your web application.
- Or send a POST request to
https://localhost:5443/scan. - Or use a deep link:
<a href="scanlink://scan?docId=123">Scan</a>
- Scanner Selection:
- The first time you scan, a dialog will ask you to select your scanner.
- Check "Set as default" to skip this step in the future.
- To change scanners later, right-click the tray icon → Clear Default Scanner.
- Status Updates:
- Poll the job status endpoint or use
static/scanlink.jsfor status tracking. - Microsys already ships the shared ScanLink helper.
- Poll the job status endpoint or use
ScanLink exposes a local REST API for browser apps:
GET http://127.0.0.1:5000/healthPOST http://127.0.0.1:5000/scanGET http://127.0.0.1:5000/scan/<job_id>GET http://127.0.0.1:5000/scan/<job_id>/result
HTTPS is prepared automatically at https://127.0.0.1:5443 on Windows. Healthy
identities are reused and renewed before expiry. /health.https_setup reports
preparing, ready, or failed; HTTP remains available while setup runs.
The certificate is a localhost-only server identity, not a certificate authority.
See architecture for trust and key storage.
Minimal browser flow:
const scanLink = new ScanLink();
const job = await scanLink.startScan({ docId: "DOC-123" });
const pdfBlob = await scanLink.waitForResult(job.job_id);Developer docs:
- Developer Guide: frontend flow, deep links, callbacks, and operational notes.
- API Reference: endpoint contracts, status payloads, and error codes.
- Architecture: how the app is wired internally.
- Building and Release: local development, PyInstaller builds, and installer packaging.
See CHANGELOG.md for the full release history.