Rustcha
rustcha recognizes CAPTCHA text from encoded images. The Python API uses a
Rust extension and bundled ONNX models, so inference does not require a network
connection.
Install
uv add rustcha
The package supports CPython 3.11 through 3.15. Building from source requires Rust 1.88 or newer.
Recognize text
Pass encoded image bytes, a path string, or a pathlib.Path:
from rustcha import Rustcha
recognizer = Rustcha()
result = recognizer.recognize(image_bytes)
print(result.text)
print(result.confidence)
allowed_characters constrains decoding to a known alphabet:
digits = recognizer.recognize(image_bytes, allowed_characters="0123456789")
Confidence is the geometric mean of the selected character probabilities. It
is None when the model returns no characters.
Detect character regions
The detection model loads on first use. Set preload_detection=True if you
prefer to pay that cost when constructing the recognizer.
recognizer = Rustcha(preload_detection=True)
result = recognizer.detect(image_bytes)
for box in result.boxes:
print(box.x_min, box.y_min, box.x_max, box.y_max, box.confidence)
include_positions=True pairs recognized characters with detections from left
to right:
result = recognizer.recognize(image_bytes, include_positions=True)
for item in result.character_positions:
print(item.character, item.box)
OCR and detection are separate model passes. Their result counts can differ;
an unmatched character has box=None. Call detect() when you need every
detection.
Batches and asyncio
One recognizer reuses one OCR session. batch_size limits how many encoded
images enter one native call; the model still evaluates images one at a time.
results = recognizer.batch_recognize(images, batch_size=10)
AsyncRustcha moves work to a worker thread. Calls on the same instance are
serialized so they can reuse the same native sessions.
from rustcha import AsyncRustcha
recognizer = AsyncRustcha()
result = await recognizer.recognize(image_bytes)
Input limits
Encoded input is limited to 32 MiB. Decoded width and height are each limited to 8,192 pixels, and image decoders receive a 128 MiB allocation budget. These limits keep malformed or unexpectedly large inputs from consuming unbounded memory. They are not a substitute for request-size limits and timeouts in a service that accepts public uploads.
Models and license
The Python API, Rust implementation, packaging, tests, and automation in this
repository are original work by Henrique Moreira and are distributed under the
project's MIT license. rustcha was inspired by
sml2h3/ddddocr, but has its own
implementation and public API.
The bundled OCR and detection ONNX models come from ddddocr and are
distributed under its MIT license. The OCR character map is derived from that
project's CHARSET_BETA, so it is attributed with the models. Exact source
details and checksums are recorded in
THIRD_PARTY_NOTICES.md,
and the upstream license is included in
licenses/ddddocr-LICENSE.
OCR output is probabilistic. Do not use it as an authentication or authorization decision without independent validation.
Development
uv sync --all-groups
uv run maturin develop
just check
just check runs Python lint and type checks, Rust formatting and Clippy,
Rust unit tests, lockfile checks, and Python integration tests.
Every push to prod checks the versions in pyproject.toml, Cargo.toml, and
uv.lock. When they match and are newer than the latest v* tag, GitHub
Actions builds CPython 3.11–3.15 ABI3 wheels for Linux, macOS ARM64, and Windows, publishes
them to PyPI with uv, then creates the tag and GitHub release. Release notes
list the commits since the previous tag in Keep a Changelog-style Added,
Changed, Fixed, and Removed sections.
The repository must contain a PYPI_API_TOKEN Actions secret. A failed release
can be resumed with the Publish Release workflow's manual trigger; identical
files already present on PyPI are checked before upload.
Metadata
Release files for rustcha 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| rustcha-0.1.0.tar.gz | 69.1 MB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| rustcha-0.1.0-cp311-abi3-win_amd64.whl | CPython 3.11 | abi3 | Windows x86-64 | Details |
| rustcha-0.1.0-cp311-abi3-manylinux_2_28_x86_64.whl | CPython 3.11 | abi3 | Linux glibc 2.28+ x86-64 | Details |
| rustcha-0.1.0-cp311-abi3-manylinux_2_28_aarch64.whl | CPython 3.11 | abi3 | Linux glibc 2.28+ ARM64 | Details |
| rustcha-0.1.0-cp311-abi3-macosx_11_0_arm64.whl | CPython 3.11 | abi3 | macOS 11.0+ ARM64 | Details |
Total release size: 379.2 MB
Release files / rustcha-0.1.0.tar.gz
| Download URL | rustcha-0.1.0.tar.gz |
|---|---|
| Size | 69.1 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f1628331d037fc906a480560c34667078839cb77ae6d86f73984de05929c4633
|
|
BLAKE2b-256 checksum How to use checksums |
9c24f054248df8e2d247d167cfe4f8c2bd7eb0d1ebf5544c5311842f9a4d237c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / rustcha-0.1.0-cp311-abi3-win_amd64.whl
| Download URL | rustcha-0.1.0-cp311-abi3-win_amd64.whl |
|---|---|
| Size | 76.6 MB |
| Tags | CPython 3.11 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
8f309fd1cb42cad96ba0b6a9af17e5ec932cbb3c7779c122c911e423757249ae
|
|
BLAKE2b-256 checksum How to use checksums |
5f4a87dbff6466e2a3479e4d033a52887f721e535a4cc49e05df5999dbe669c0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / rustcha-0.1.0-cp311-abi3-manylinux_2_28_x86_64.whl
| Download URL | rustcha-0.1.0-cp311-abi3-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 78.1 MB |
| Tags | CPython 3.11 Linux glibc 2.28+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
5268e06f353c0c6d00af91209280e34e069ea80eb6ca905dda7f3bbebc99cb2d
|
|
BLAKE2b-256 checksum How to use checksums |
bff8339334387858a18a25429611674e3f197c94b36070cf3deac210382501c9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / rustcha-0.1.0-cp311-abi3-manylinux_2_28_aarch64.whl
| Download URL | rustcha-0.1.0-cp311-abi3-manylinux_2_28_aarch64.whl |
|---|---|
| Size | 78.8 MB |
| Tags | CPython 3.11 Linux glibc 2.28+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
51a3f9c7b48a5e7f1e501a0b92d04d44bc29c7f947a8e7f92d67ea5fe4c0389f
|
|
BLAKE2b-256 checksum How to use checksums |
659a7675a56dfd77bc8f261718233d921344bf88ed7ccae0d4c6674f41c6c3a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / rustcha-0.1.0-cp311-abi3-macosx_11_0_arm64.whl
| Download URL | rustcha-0.1.0-cp311-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 76.6 MB |
| Tags | CPython 3.11 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
c6d82f989fd74acf366fd564a6eba493410e05878cd91b74511e707534abd24d
|
|
BLAKE2b-256 checksum How to use checksums |
eb21c3aba8576be4ad6ac4eab5154cd182cf2dff92e3f7e40fac4077c56af6d5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|