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.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rustcha-0.1.0.tar.gz.
File metadata
- Download URL: rustcha-0.1.0.tar.gz
- Upload date:
- Size: 69.1 MB
- Tags: Source
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f1628331d037fc906a480560c34667078839cb77ae6d86f73984de05929c4633
|
|
| MD5 |
a962081c26e7a11790b10ee2d6dc0b33
|
|
| BLAKE2b-256 |
9c24f054248df8e2d247d167cfe4f8c2bd7eb0d1ebf5544c5311842f9a4d237c
|
File details
Details for the file rustcha-0.1.0-cp311-abi3-win_amd64.whl.
File metadata
- Download URL: rustcha-0.1.0-cp311-abi3-win_amd64.whl
- Upload date:
- Size: 76.6 MB
- Tags: CPython 3.11+, Windows x86-64
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8f309fd1cb42cad96ba0b6a9af17e5ec932cbb3c7779c122c911e423757249ae
|
|
| MD5 |
90224b19c653d8e3626149fed480d473
|
|
| BLAKE2b-256 |
5f4a87dbff6466e2a3479e4d033a52887f721e535a4cc49e05df5999dbe669c0
|
File details
Details for the file rustcha-0.1.0-cp311-abi3-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: rustcha-0.1.0-cp311-abi3-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 78.1 MB
- Tags: CPython 3.11+, manylinux: glibc 2.28+ x86-64
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5268e06f353c0c6d00af91209280e34e069ea80eb6ca905dda7f3bbebc99cb2d
|
|
| MD5 |
a74a63d9dc6c930a5b85a4e5cac7197c
|
|
| BLAKE2b-256 |
bff8339334387858a18a25429611674e3f197c94b36070cf3deac210382501c9
|
File details
Details for the file rustcha-0.1.0-cp311-abi3-manylinux_2_28_aarch64.whl.
File metadata
- Download URL: rustcha-0.1.0-cp311-abi3-manylinux_2_28_aarch64.whl
- Upload date:
- Size: 78.8 MB
- Tags: CPython 3.11+, manylinux: glibc 2.28+ ARM64
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
51a3f9c7b48a5e7f1e501a0b92d04d44bc29c7f947a8e7f92d67ea5fe4c0389f
|
|
| MD5 |
fe9661358d67e5ad6f3b7ba4fef78355
|
|
| BLAKE2b-256 |
659a7675a56dfd77bc8f261718233d921344bf88ed7ccae0d4c6674f41c6c3a7
|
File details
Details for the file rustcha-0.1.0-cp311-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: rustcha-0.1.0-cp311-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 76.6 MB
- Tags: CPython 3.11+, macOS 11.0+ ARM64
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c6d82f989fd74acf366fd564a6eba493410e05878cd91b74511e707534abd24d
|
|
| MD5 |
261c9f81e0d3a44559c1824a1f7df9e9
|
|
| BLAKE2b-256 |
eb21c3aba8576be4ad6ac4eab5154cd182cf2dff92e3f7e40fac4077c56af6d5
|