A pluggable Python CAPTCHA library supporting image-based text challenges, arithmetic challenges, audio challenges, token-based security, and multiple storage backends.
PyPI · GitHub · Issues · Discussions
pip install InnoCaptchaGenerates an image-based CAPTCHA with configurable text, colors, and dimensions. All images include random distortions and anti-aliasing.
from InnoCaptcha.text import TextCaptcha
# Basic usage
captcha = TextCaptcha()
captcha.create("abs")
print(captcha.verify("abs")) # True
captcha.save(r"captcha.png")
# Custom dimensions and colors
captcha = TextCaptcha(
width=350,
height=100,
color=(255, 137, 6),
background=(15, 14, 23)
)
captcha.create("abc123")
print(captcha.verify("wrong")) # False
captcha.save(r"captcha.jpg")Constructor Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
width |
int or None |
300 |
Image width in pixels. |
height |
int or None |
80 |
Image height in pixels. |
color |
tuple[int, int, int] |
(0, 0, 0) |
Foreground (text) color in RGB. |
background |
tuple[int, int, int] |
(255, 255, 255) |
Background color in RGB. |
create(chars: str) — The text string to render in the CAPTCHA image. Required.
save() Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
path |
str |
'captcha.png' |
Full file path or file name to write the image. |
Notes:
- Uses
secretsfor cryptographically strong randomness.- Rendering can be tuned via module-level constants such as
CHARACTER_OFFSET_DXandWORD_SPACE_PROBABILITY.
Generates arithmetic challenges (addition, subtraction, multiplication, division). All results are integers — the problem regenerates automatically if division would produce a fraction.
from InnoCaptcha.math import MathCaptcha
challenge = MathCaptcha()
print(challenge.get_question()) # e.g., "7 + 3 = ?"
print(challenge.answer) # e.g., 10
print(challenge.verify(10)) # True
print(challenge.verify("10")) # True — string input acceptedGenerates a spoken character sequence as a WAV file. Each character is spliced from pre-recorded audio samples stored in the data/ directory, with per-character noise injection, randomized playback speed, and a low-pass filter applied to the combined output. Challenge state is persisted in SQLite with a 5-minute expiry and a 5-attempt limit.
from InnoCaptcha.audio import AudioCaptcha
# Basic usage
captcha = AudioCaptcha()
captcha.create("ab3")
captcha.save("captcha.wav")
print(captcha.verify("ab3")) # True
print(captcha.verify("wrong")) # Falsecreate(chars: str) — Accepts up to 6 characters. Each character must have a corresponding <char>.wav file in the data/ directory. Raises FileNotFoundError if any file is missing.
save() Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
path |
str |
— | Full file path to write the output WAV file. |
verify(user_input: str) -> bool or str
| Return value | Condition |
|---|---|
True |
Input matches the stored answer (case-insensitive). |
False |
Input does not match; attempt counter incremented. |
str (error message) |
Captcha expired or maximum attempts (5) reached. |
Notes:
- Uses
secretsfor randomness in noise generation and speed variation.- A background thread runs on instantiation to purge expired records from the database.
- Output is a 44100 Hz, 16-bit, mono WAV file.
# Display the installed version
InnoCaptcha --version
# Upgrade to the latest release on PyPI
InnoCaptcha --upgrade| Method / Attribute | Description |
|---|---|
create(chars: str) |
Renders the given string into a distorted CAPTCHA image. |
verify(input: str) |
Returns True if input matches the generated text. |
save(path) |
Writes the image to the specified file path. |
| Method / Attribute | Description |
|---|---|
get_question() -> str |
Returns the challenge string, e.g. "7 + 3 = ?". |
answer: int |
The correct integer answer to the current challenge. |
verify(input) -> bool |
Returns True if input equals the answer. |
| Method / Attribute | Description |
|---|---|
create(chars: str) |
Builds the audio challenge from up to 6 characters using per-character WAV files. |
verify(input: str) |
Returns True on match, False on mismatch, or a str on expiry/lockout. |
save(path: str) |
Writes the generated audio to a 44100 Hz 16-bit mono WAV file. |
id: str |
The hex token identifying this challenge in the database. |
audio: np.ndarray |
Raw float32 audio samples; None until create() is called. |
- Python 3.9 or later
- Pillow >= 10.0.0
- numpy
- scipy
MIT — InnoSoft Company