Skip to main content

Tapirscan for Python

scan(image) returns every decoded barcode: result.values gives the decoded strings and result.barcodes pairs each one with its format and source-image polygon / rect. Both are empty when nothing is decoded.

Try the live demo · Quick start · Functions · All options · Results

import tapirscan

result = tapirscan.scan(image)
print(result.values)
for barcode in result.barcodes:
    print(barcode.text, barcode.polygon)

image can be a Pillow image, a NumPy array or a PyTorch tensor. Use inspect instead of scan for timing, unread regions and diagnostics.

Installation

Python 3.10+ is required. Platform wheels bundle the native library with all four effort modes:

pip install tapirscan

Quick start

Tapirscan has no image-library dependencies; install the ones your inputs need.

TIFF with tifffile

pip install tapirscan tifffile
import tifffile
import tapirscan

pixels = tifffile.imread("label.tif", key=0)  # NumPy array: first TIFF page
result = tapirscan.scan(pixels)
print(result.values)

This assumes an 8-bit grayscale or RGB image. Defaults are Medium effort and the retail formats (EAN13, UPCA, EAN8, UPCE).

JPEG with Pillow

pip install tapirscan pillow
from PIL import Image
import tapirscan

with Image.open("label.jpg") as image:
    result = tapirscan.scan(image, mode="high", formats="1D")

for barcode in result.barcodes:
    print(barcode.text, barcode.format, barcode.polygon)

formats="1D" enables all linear formats. "retail" selects EAN13, UPCA, EAN8 and UPCE; "common1D" adds Code128, Code39 and ITF; "common" adds QRCode and DataMatrix; "2D" and "all" are also available. See format coverage.

PyTorch tensors

pip install tapirscan torch
import torch

tensor = torch.from_numpy(pixels)  # the array from the TIFF example
result = tapirscan.scan(tensor)
print(result.values)

GPU tensors and tensors with requires_grad=True work directly: Tapirscan copies the pixels to CPU without changing your tensor or its autograd graph. Decoding runs on CPU. See array and tensor inputs.

Functions

# One image, with automatic cleanup:
result = tapirscan.scan(image, mode="medium", formats=["EAN13"])

# Reuse native initialization across images:
with tapirscan.Scanner(mode="high", formats="1D") as scanner:
    result = scanner.scan(image)
    print(result.values)

Signatures (all settings are optional). inspect and scanner.inspect take the same arguments as their scan counterparts and return InspectionResult:

scan(image, *, mode="medium", formats=None, ean_add_on_policy="ignore",
     layout="auto", value_range="auto", color_order="RGB", library_dir=None) -> ScanResult
Scanner(mode="medium", *, formats=None, ean_add_on_policy="ignore", library_dir=None)
scanner.scan(image, *, formats=None,
             layout="auto", value_range="auto", color_order="RGB") -> ScanResult
scanner.close()

Use the context manager or call close() in a finally block; repeated close() is safe and results stay valid afterwards. Calls on one scanner run one at a time; separate scanners can run concurrently. scanner.mode and scanner.formats are read-only; create another scanner to change effort. Per-call formats apply to that call only; None uses the scanner's selection.

All options

Option Where Default Meaning
mode Creation / one-shot "medium" "low", "medium", "high", "very-high".
formats Creation / scan retail An identifier, "retail", "common1D", "common", "1D", "2D", "all", or a nonempty list/tuple of identifiers.
ean_add_on_policy Creation / one-shot "ignore" "ignore", "read", "require"; see supplements.
layout Scan, arrays/tensors only "auto" "HW", "HWC", "CHW"; specify when the channel position is ambiguous.
value_range Scan, arrays/tensors only "auto" "0_1" or "0_255". Auto uses [0,1] for floats and [0,255] for integers, independent of image contents.
color_order Scan, arrays/tensors only "RGB" "BGR" for OpenCV BGR/BGRA pixels. Grayscale is unaffected.
library_dir Creation / one-shot Bundled library Directory of a custom native build. Lookup order: this argument, TAPIRSCAN_LIBRARY_DIR, then the wheel's library.

Effort modes tune EAN/UPC, common linear formats, QR Code, Data Matrix and Aztec; PDF417 and MaxiCode use a fixed effort. Format group exports: retail_formats, common_linear_formats, common_formats, linear_formats, matrix_formats. Resizing, cropping, rotation and camera capture are up to the caller.

Image input

Array and tensor inputs

One HW/HWC/CHW image, optionally with a leading batch axis of size one, with 1, 3 or 4 channels. NumPy views and noncontiguous tensors are accepted. Colors default to RGB/RGBA. Booleans become black/white. NaN, infinity and out-of-range values are rejected rather than clipped: scale higher-bit-depth intensities and undo mean/std normalization first. Floats stored in byte units need value_range="0_255".

CUDA, MPS and other device tensors are copied to CPU, which adds latency. Sparse, quantized, complex and meta tensors are rejected.

OpenCV

import cv2
import tapirscan

image = cv2.imread("label.jpg")
if image is None:
    raise ValueError("Could not load label.jpg")
result = tapirscan.scan(image, color_order="BGR")

OpenCV is not a dependency. color_order="BGR" does not modify your array.

Pillow

Pillow I, F and I;16* images are read as intensities in [0,255], matching Pillow's usual conversion convention; scale higher-bit-depth images explicitly. layout, value_range and color_order do not apply to Pillow images.

Raw pixels

image = tapirscan.PixelImage(pixels, width=640, height=480, channels=3)
result = tapirscan.scan(image)

pixels contains decoded bytes, not a JPEG/PNG file.

PixelImage field Default Meaning
data Required, positional bytes, bytearray, or a contiguous byte memoryview.
width, height Required, keyword-only Integer dimensions, at least 3 pixels each.
channels 1 1 grayscale, 3 RGB, 4 RGBA. Alpha is ignored.
stride width * channels Bytes between row starts. Larger values allow padding.

Storage must cover (height - 1) * stride + width * channels bytes.

Limits

Images may have at most 32 megapixels and 128 MiB of pixel data; this is checked before any conversion or device transfer. Coordinates start at the top left. If you resize before scanning, map coordinates back when drawing on the original.

Results

scan returns a ScanResult; inspect returns an InspectionResult with the same fields plus the ones marked inspect. Results are immutable.

Field/method Meaning
result.values List of decoded strings, one per barcode.
result.barcodes Tuple of immutable Barcode objects.
result.best Highest-support barcode (first on ties), or None.
result.as_dict() JSON-compatible dictionary of the public fields, without diagnostics.
result.image inspect: ImageSize(width, height) of the supplied pixels.
result.mode inspect: effort mode used.
result.elapsed_ms inspect: native scan time, excluding image conversion.
result.undecoded inspect: regions without a decode.
result.diagnostics inspect: engine evidence.
barcode.text, .format Decoded text and format identifier.
barcode.polygon Tuple of four Point(x, y) source-image coordinates.
barcode.rect Enclosing integer Rect(left, top, width, height).
barcode.support Reader-specific ranking evidence used by best.
barcode.payload_bytes Decoded matrix payload bytes, or None.
barcode.gs1 GS1 indicator, or None if not supplied by the reader.
barcode.reader_initialization Data Matrix, PDF417, Aztec and MaxiCode reader-initialization flag; None for other formats.
barcode.structured_append StructuredAppend(index, count, id, parity), or None; index is one-based.
barcode.ean_add_on EAN/UPC supplement, with ean_add_on_policy "read" or "require".

Separate labels with the same value stay separate entries. barcode.as_dict() exports a single read, and json.dumps(result.as_dict()) works directly.

support is an uncalibrated, reader-specific ranking heuristic, not a probability, and is not comparable across formats. In a mixed-format image, best is therefore not necessarily the most reliable read; select by format or payload when your application knows what it expects. Checksums reduce wrong reads but cannot rule them out.

payload_bytes is supplied by QR Code, Data Matrix, Aztec, PDF417 and MaxiCode. It holds decoded data bytes before character-set interpretation, not raw codewords; Aztec Rune gives its value as decimal ASCII. Encoding text as UTF-8 does not reconstruct these bytes.

Exported types include ScanResult, InspectionResult, Barcode, Format, FormatSelection, Mode, Layout, ValueRange, ColorOrder, ImageInput and PixelImage. The package includes py.typed.

EAN/UPC supplements

Set ean_add_on_policy when creating a scanner or calling one-shot scan or inspect.

Policy Behavior
"ignore" Decode the main barcode without reading its supplement.
"read" Try reading the two- or five-digit supplement; keep the main barcode if none is readable.
"require" Return an EAN/UPC barcode only when its supplement is readable. Other formats remain unaffected.

The supplement appears in barcode.ean_add_on; barcode.text is the main payload, and polygon and rect describe the main barcode. Reading supplements adds decoding work. Retail reads rejected by "require" appear in result.undecoded.

Undecoded regions

inspect results list undecoded regions: localized proposals without an accepted decode, each with a source-image polygon and a format hint ("Unknown" when unavailable). They can overlap or be false candidates, and an empty list does not prove that every barcode was found.

Diagnostics

report = tapirscan.inspect(image)
regions = report.diagnostics.regions
if regions is not None:
    print(regions.proposals, regions.search_windows, regions.candidates)

proposals and search_windows are None when a reader does not expose them, and empty tuples when it found nothing. report.diagnostics.barcodes lists per-read evidence; region types are in tapirscan.results. report.diagnostics.to_raw_dict() returns the engine's own JSON evidence, whose fields vary by reader and may change between releases. Candidate indices inside a recovery crop are local to that crop, not identifiers for tracking between frames.

Errors

Invalid input raises ValueError or TypeError. Native failures raise ScannerError with a message, the native .status number and a .code shared with JavaScript: "invalid_input", "disposed" or "engine". Scanning after close() raises RuntimeError. A custom native library from library_dir must implement native ABI 6; mismatches are reported with rebuild instructions.

License

Tapirscan is dual-licensed under MIT OR Apache-2.0, at your option. See the full license texts. Third-party components retain their own licenses and notices.

Metadata

Release files for tapirscan 1.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for tapirscan 1.3.0
File
tapirscan-1.3.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
tapirscan-1.3.0-py3-none-manylinux_2_28_x86_64.whl Python 3 none Linux glibc 2.28+ x86-64 Details
tapirscan-1.3.0-py3-none-manylinux_2_28_aarch64.whl Python 3 none Linux glibc 2.28+ ARM64 Details
tapirscan-1.3.0-py3-none-macosx_11_0_x86_64.whl Python 3 none macOS 11.0+ x86-64 Details
tapirscan-1.3.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details

Total release size: 15.4 MB

Release files / tapirscan-1.3.0-py3-none-win_amd64.whl

Download URL tapirscan-1.3.0-py3-none-win_amd64.whl
Size 3.0 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
e71da760f73af45fed2ea468a7f0efa8ca6829553bbfac47f2da14e3a071f434
BLAKE2b-256 checksum
How to use checksums
5addc17c41e3400d333b8385fdd2a21fa2ce806bfb254725e86eb5fda2a5de74
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release files / tapirscan-1.3.0-py3-none-manylinux_2_28_x86_64.whl

Download URL tapirscan-1.3.0-py3-none-manylinux_2_28_x86_64.whl
Size 3.4 MB
Tags Linux glibc 2.28+ x86-64 Python 3
SHA-256 checksum
How to use checksums
c7f431b03584c569e789355f5e66b4442c65c91353a4dcbb3ca9fee8e50f5637
BLAKE2b-256 checksum
How to use checksums
d9daa891f3752b09254c71567d5887695914d3e2ac42ac1e4a15034a59f0a182
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release files / tapirscan-1.3.0-py3-none-manylinux_2_28_aarch64.whl

Download URL tapirscan-1.3.0-py3-none-manylinux_2_28_aarch64.whl
Size 2.9 MB
Tags Linux glibc 2.28+ ARM64 Python 3
SHA-256 checksum
How to use checksums
d78c377355c931e4a1d5b95daaf56ca2bd9eba036e994463c06f1deac276ae0b
BLAKE2b-256 checksum
How to use checksums
d535f54b17d707966895aa3f773f612e8dff611f50e0f5270945504ea1ea05f3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release files / tapirscan-1.3.0-py3-none-macosx_11_0_x86_64.whl

Download URL tapirscan-1.3.0-py3-none-macosx_11_0_x86_64.whl
Size 3.3 MB
Tags Python 3 macOS 11.0+ x86-64
SHA-256 checksum
How to use checksums
b076414aff06afe277422da3380c70ff9daf404122b09eb59218e98501097069
BLAKE2b-256 checksum
How to use checksums
3d9a1eca0f1aff393100ee2cdf7c9a2f6a6226b7fe1991783b9300513df3d5c6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release files / tapirscan-1.3.0-py3-none-macosx_11_0_arm64.whl

Download URL tapirscan-1.3.0-py3-none-macosx_11_0_arm64.whl
Size 2.9 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
06f73c6d5c3aa77596f09f11ad3dc912541cbfc08a8e73284e63972d0ab12228
BLAKE2b-256 checksum
How to use checksums
3c6d43f218cae2e63c2638cf6603aa4f1d88e64bb8154b2dca2b54237d1c6d06
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.3.0 This release

5 release files

1.2.2

5 release files

1.2.1

5 release files

1.2.0

5 release files

1.1.0

5 release files

1.0.0

5 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page