API Reference

Scanner Discovery

scanlib.list_scanners(*, timeout=15.0, cancel=None)

Return all available scanners on the current platform.

timeout controls how long (in seconds) to wait for scanner discovery. The default is DISCOVERY_TIMEOUT (15 s).

cancel, if given, is a threading.Event that the caller can set from another thread to interrupt discovery early. When the event is set the function returns immediately with an empty list.

The returned Scanner objects are lightweight — no device sessions are opened. Use Scanner.open() (or the context-manager protocol) to start a session before scanning.

Return type:

list[Scanner]

Parameters:

Scanner

class scanlib.Scanner(name, vendor, model, backend, *, scanner_id=None, location=None, uuid=None, display_name=None, _backend_impl=None)

Represents a discovered scanner device.

Use open() / close() (or the context-manager protocol) to start a session before calling scan().

Parameters:
  • name (str)

  • vendor (str | None)

  • model (str | None)

  • backend (str)

  • scanner_id (str | None)

  • location (str | None)

  • uuid (str | None)

  • display_name (str | None)

  • _backend_impl (ScanBackend | None)

property name: str

Platform-specific device name.

On SANE this is the device URI (e.g. escl:http://192.168.1.5:443/eSCL), on macOS and WIA it is a human-readable display name. Always populated.

property id: str

Platform-opaque string that uniquely identifies this device.

Guaranteed unique across all scanners returned by a single list_scanners() call. On SANE this is the device URI, on WIA the device ID, on macOS the device UUID.

property uuid: str | None

Lower-cased device UUID, or None when not available.

Populated on macOS (where it equals id), on WIA for network/WSD scanners (extracted from the WSD port name), and on eSCL (from the mDNS UUID record). None on SANE. Used by the composite backend to recognise that a platform scanner and an eSCL scanner are the same physical device.

property vendor: str | None

Scanner manufacturer, or None when not available.

Populated on SANE and macOS; None on WIA where WSD reports the driver vendor rather than the hardware manufacturer.

property model: str | None

Scanner model string, or None when not available.

Populated on SANE only; None on macOS and WIA.

property location: str | None

Free-form location string associated with the device.

Populated from ICDevice.locationDescription on macOS, or from the mDNS note TXT record on Linux/Windows. Returns None when no location is available.

property backend: str

"sane", "imagecapture", "wia", or "escl".

Type:

Backend identifier

property is_open: bool

Whether a device session is currently open.

property sources: list[SourceInfo]

Available scan sources and their capabilities.

Each entry is a SourceInfo with type, resolutions, color_modes, and max_scan_area. Only populated after open().

The first entry is the scanner’s primary source (typically flatbed). When scan() or scan_pages() is called without an explicit source, the first entry is used for parameter validation.

property defaults: ScannerDefaults | None

Default settings and supported values detected from the device.

Returns None if the backend could not determine defaults. Only available after open().

open()

Open a session on the scanner device. Returns self.

Return type:

Scanner

close()

Close the scanner session.

Return type:

None

abort()

Abort an in-progress scan.

Safe to call from any thread, even when no scan is running. The running scan() or scan_pages() call will raise ScanAborted shortly after this is called. The event is cleared automatically at the start of the next scan.

Return type:

None

scan_pages(*, dpi=300, color_mode=ColorMode.COLOR, scan_area=None, source=None, progress=None, next_page=None, bw_threshold=128)

Scan and yield individual ScannedPage objects.

Each page carries raw pixel data that can be inspected, encoded (via ScannedPage.to_jpeg() / ScannedPage.to_png()), reordered, or later assembled into a PDF with build_pdf().

When next_page is provided and the source is not a feeder, each page is yielded before the callback is invoked, so the caller can preview or process the page before deciding whether to continue scanning.

Parameters:
  • progress (Callable[[int], bool] | None) – Optional callback invoked repeatedly while scanning with an int percentage from 0 to 100, or -1 while the scanner is working but no percentage is yet available (e.g. warming up or feeding a page). Return True (or None) to continue; returning False aborts the scan and raises ScanAborted. Depending on the backend the callback may run on an internal worker thread, so marshal any GUI updates to your own UI thread.

  • next_page (Callable[[int], bool] | None) – Optional callback for flatbed multi-page scans; called with the number of pages scanned so far after each page. Return True to scan another page or False to stop. Ignored for feeder sources (which scan every sheet automatically).

  • bw_threshold (int) – Grayscale-to-BW cutoff (0–255) used when color_mode is ColorMode.BW. Pixels with a value ≥ threshold become white; below become black. Default is 128.

  • dpi (int)

  • color_mode (ColorMode)

  • scan_area (ScanArea | None)

  • source (ScanSource | None)

Return type:

Iterator[ScannedPage]

Other parameters are the same as scan() except that image_format and jpeg_quality are not applicable here.

scan(*, dpi=300, color_mode=ColorMode.COLOR, scan_area=None, source=None, progress=None, next_page=None, image_format=None, jpeg_quality=85, bw_threshold=128)

Scan a document and return PDF bytes.

When source is ScanSource.FEEDER, all pages in the document feeder are scanned. Otherwise a single page is scanned.

Parameters:
  • progress (Callable[[int], bool] | None) – Optional callback invoked repeatedly while scanning with an int percentage from 0 to 100, or -1 while the scanner is working but no percentage is yet available. Return True (or None) to continue; returning False aborts the scan and raises ScanAborted. May run on an internal worker thread depending on the backend.

  • next_page (Callable[[int], bool] | None) – Optional callback for flatbed multi-page scans, called after each page with the number of pages scanned so far. Return True to scan another page or False to stop. Ignored for feeder sources, which scan every sheet automatically.

  • image_format (ImageFormat | None) – Encoding for page images inside the PDF — ImageFormat.JPEG (smaller files) or ImageFormat.PNG (lossless). When not specified, PNG is used for BW mode (1-bit packs much smaller than JPEG) and JPEG for everything else.

  • jpeg_quality (int) – JPEG compression quality (1–100); ignored when image_format is PNG.

  • bw_threshold (int) – Grayscale-to-BW cutoff (0–255) used when color_mode is ColorMode.BW. Default is 128.

  • dpi (int)

  • color_mode (ColorMode)

  • scan_area (ScanArea | None)

  • source (ScanSource | None)

Return type:

ScannedDocument

Scanned Pages

class scanlib.ScannedPage(data, width, height, color_mode)

A single scanned page with raw pixel data.

data contains raw pixel bytes with no header or wrapper — 1 byte per pixel for grayscale (ColorMode.GRAY), 3 bytes per pixel (R, G, B) for color (ColorMode.COLOR), or 1-bit packed (MSB first) for black & white (ColorMode.BW).

Parameters:
rotate(degrees)

Rotate the page clockwise by 90, 180, or 270 degrees.

Returns a new ScannedPage with the rotated pixel data. For 90° and 270° rotations, width and height are swapped.

Return type:

ScannedPage

Parameters:

degrees (int)

to_jpeg(quality=85)

Encode the page as JPEG and return the bytes.

Uses a platform-native encoder (ImageIO on macOS, WIC on Windows, libjpeg on Linux). quality ranges from 1 (smallest) to 100 (best). 1-bit BW pages are unpacked to 8-bit grayscale before encoding.

Return type:

bytes

Parameters:

quality (int)

to_png()

Encode the page as lossless PNG and return the bytes.

Uses stdlib zlib for compression — no external dependency.

Return type:

bytes

scanlib.build_pdf(pages, *, dpi=300, color_mode=ColorMode.COLOR, image_format=None, jpeg_quality=85, bw_threshold=128)

Build a PDF from scanned pages.

pages is any iterable of ScannedPage objects — they may come directly from Scanner.scan_pages() or from a list that has been reordered, filtered, etc.

image_format selects the encoding for page images inside the PDF: ImageFormat.JPEG (smaller files) or ImageFormat.PNG (lossless). When not specified, PNG is used for BW mode (since 1-bit packs much smaller than JPEG) and JPEG for everything else. jpeg_quality (1–100) controls JPEG compression; it is ignored when the format is PNG.

bw_threshold (0–255) controls the grayscale-to-BW cutoff when color_mode is ColorMode.BW. Default is 128.

Returns a ScannedDocument containing the PDF bytes.

Return type:

ScannedDocument

Parameters:

Scan Result

class scanlib.ScannedDocument(data, page_count, width, height, dpi, color_mode)

Result of a scan operation.

data contains PDF file bytes (one or more pages). width and height reflect the dimensions of the first page in pixels. Individual pages in the PDF may differ (e.g. after rotation).

Parameters:
width: int

Width of the first page in pixels.

height: int

Height of the first page in pixels.

Options & Configuration

class scanlib.ScanOptions(dpi=300, color_mode=ColorMode.COLOR, scan_area=None, source=None, progress=None, bw_threshold=128)

Options for a scan operation.

Parameters:
class scanlib.ColorMode(*values)

Color mode for scanning.

COLOR = 'color'
GRAY = 'gray'
BW = 'bw'
class scanlib.ScanSource(*values)

Scan source type.

FLATBED = 'flatbed'
FEEDER = 'feeder'
class scanlib.ImageFormat(*values)

Image encoding format used inside the PDF.

PNG = 'png'
JPEG = 'jpeg'
class scanlib.ScanArea(x, y, width, height)

Scan region in 1/10 millimeters.

x and y are offsets from the top-left corner of the scanner bed. width and height are the dimensions of the region to scan.

Parameters:
class scanlib.ScannerDefaults(dpi, color_mode, source)

Default settings detected from the device after opening.

Parameters:
class scanlib.SourceInfo(type, resolutions, color_modes, max_scan_area)

Capabilities of a single scan source.

Each SourceInfo bundles the supported resolutions, color modes, and maximum scan area for one scan source (flatbed or feeder). Access via Scanner.sources after opening the device.

Parameters:

Exceptions

class scanlib.ScanLibError

Base exception for scanlib.

class scanlib.ScanError

An error occurred during scanning.

class scanlib.ScanAborted

The scan was aborted before completion.

class scanlib.FeederEmptyError

The document feeder has no pages to scan.

class scanlib.ScannerBusyError(message='Scanner is in use by another session or application. Close it and try again.')

The scanner is in use by another session or application.

Parameters:

message (str)

class scanlib.ScannerUnavailableError(message='Scanner is unavailable it may be offline, asleep, or disconnected. Check that it is powered on and reachable, then try again.')

The scanner could not be reached (offline, asleep, or disconnected).

Unlike ScannerBusyError, the device is not held by another session — it simply did not respond. This is often transient (a network scanner that has gone to sleep) and worth retrying once the device is reachable again.

Parameters:

message (str)

class scanlib.ScannerNotOpenError

Operation requires an open scanner session.

class scanlib.NoScannerFoundError

No scanner device was found.

class scanlib.BackendNotAvailableError

The scanning backend for this platform is not installed.