A very simple, yet powerful, Django captcha application for adding CAPTCHA image challenges to forms
—
Django Simple Captcha provides extensive configuration options for customizing captcha appearance, challenge generation, image processing, and behavior. All settings can be configured in Django's settings.py file using the CAPTCHA_* prefix.
Configuration options for customizing the visual appearance of captcha images.
# Font configuration
CAPTCHA_FONT_PATH = '/path/to/font.ttf' # str or list of font paths
CAPTCHA_FONT_SIZE = 22 # int, font size in points
# Image styling
CAPTCHA_BACKGROUND_COLOR = '#ffffff' # str, hex color for background
CAPTCHA_FOREGROUND_COLOR = '#001100' # str, hex color for text
CAPTCHA_LETTER_ROTATION = (-35, 35) # tuple, rotation range in degrees
CAPTCHA_IMAGE_SIZE = None # tuple, fixed (width, height) or None for auto
# High-resolution support
CAPTCHA_2X_IMAGE = True # bool, enable 2x resolution imagesConfiguration for different types of captcha challenges and their parameters.
# Challenge type and length
CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.random_char_challenge' # str or callable
CAPTCHA_LENGTH = 4 # int, challenge text length
# Dictionary-based challenges
CAPTCHA_WORDS_DICTIONARY = '/usr/share/dict/words' # str, path to word list file
CAPTCHA_DICTIONARY_MIN_LENGTH = 0 # int, minimum word length
CAPTCHA_DICTIONARY_MAX_LENGTH = 999 # int, maximum word length
CAPTCHA_PUNCTUATION = '.,;:' # str, punctuation for word challenges
# Math challenge customization
CAPTCHA_MATH_CHALLENGE_OPERATOR = '*' # str, display operator in math challengesConfiguration for noise functions, filters, and image processing effects.
# Noise and filter functions
CAPTCHA_NOISE_FUNCTIONS = ( # tuple of noise function names/callables
'captcha.helpers.noise_arcs',
'captcha.helpers.noise_dots',
)
CAPTCHA_FILTER_FUNCTIONS = ( # tuple of filter function names/callables
'captcha.helpers.post_smooth',
)
# Custom color function
CAPTCHA_LETTER_COLOR_FUNCT = None # str or callable for custom letter coloringConfiguration for captcha lifecycle, performance optimization, and operational behavior.
# Expiration and lifecycle
CAPTCHA_TIMEOUT = 5 # int, expiration timeout in minutes
# Performance optimization
CAPTCHA_GET_FROM_POOL = False # bool, use pre-generated captcha pool
CAPTCHA_GET_FROM_POOL_TIMEOUT = 5 # int, pool timeout in minutes
# Testing and development
CAPTCHA_TEST_MODE = False # bool, disable validation for testingConfiguration for text-to-speech audio captcha functionality.
# Audio generation paths
CAPTCHA_FLITE_PATH = '/usr/bin/flite' # str, path to flite text-to-speech binary
CAPTCHA_SOX_PATH = '/usr/bin/sox' # str, path to sox audio processing binaryBuilt-in challenge generator functions that can be used with CAPTCHA_CHALLENGE_FUNCT.
def math_challenge():
"""
Generate simple arithmetic problems (addition, subtraction, multiplication).
Returns:
tuple: (challenge_text, expected_response)
Example: ('2 + 3 = ?', '5')
"""
def random_char_challenge():
"""
Generate random alphanumeric character string.
Returns:
tuple: (challenge_text, expected_response)
Example: ('AB3F', 'AB3F')
"""
def unicode_challenge():
"""
Generate challenge using unicode characters.
Returns:
tuple: (challenge_text, expected_response)
"""
def word_challenge():
"""
Generate challenge using dictionary words.
Returns:
tuple: (challenge_text, expected_response)
Requires: CAPTCHA_WORDS_DICTIONARY setting
"""
def huge_words_and_punctuation_challenge():
"""
Generate challenge with large words and punctuation.
Returns:
tuple: (challenge_text, expected_response)
"""
def random_letter_color_challenge(idx, plaintext_captcha):
"""
Generate random color for individual letters in captcha.
Parameters:
- idx: int, letter index in the captcha
- plaintext_captcha: str, the complete captcha text
Returns:
str: Hex color string (e.g., "#FF5733")
"""Built-in functions for adding visual noise and post-processing effects to captcha images.
def noise_arcs(draw, image):
"""
Add curved arc noise to captcha image.
Parameters:
- draw: PIL ImageDraw object
- image: PIL Image object
"""
def noise_dots(draw, image):
"""
Add random dot noise to captcha image.
Parameters:
- draw: PIL ImageDraw object
- image: PIL Image object
"""
def noise_null(draw, image):
"""
No-operation noise function (no visual noise added).
Parameters:
- draw: PIL ImageDraw object
- image: PIL Image object
"""
def post_smooth(image):
"""
Apply smoothing filter to reduce image harshness.
Parameters:
- image: PIL Image object
Returns:
PIL.Image: Filtered image
"""Utility functions for loading and processing configuration settings.
def _callable_from_string(string_or_callable):
"""
Import callable from string module path.
Parameters:
- string_or_callable: str or callable
Returns:
callable: Imported function or original callable
"""
def get_challenge(generator=None):
"""
Get challenge generator function from settings or parameter.
Parameters:
- generator: str or callable, override default generator (optional)
Returns:
callable: Challenge generator function
"""
def noise_functions():
"""
Get configured noise function generators.
Returns:
list: List of noise function callables
"""
def filter_functions():
"""
Get configured filter function generators.
Returns:
list: List of filter function callables
"""
def get_letter_color(index, challenge):
"""
Get color for specific letter in challenge.
Parameters:
- index: int, letter position in challenge
- challenge: str, complete challenge text
Returns:
str: Color value for the letter
"""# In settings.py
CAPTCHA_FONT_SIZE = 24
CAPTCHA_LENGTH = 6
CAPTCHA_TIMEOUT = 10 # 10 minutes
CAPTCHA_BACKGROUND_COLOR = '#f0f0f0'
CAPTCHA_FOREGROUND_COLOR = '#333333'# Use math challenges instead of random text
CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.math_challenge'
CAPTCHA_MATH_CHALLENGE_OPERATOR = '+'
CAPTCHA_LENGTH = 1 # Not used for math challenges# Use dictionary words for challenges
CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.word_challenge'
CAPTCHA_WORDS_DICTIONARY = '/usr/share/dict/words'
CAPTCHA_DICTIONARY_MIN_LENGTH = 4
CAPTCHA_DICTIONARY_MAX_LENGTH = 8# Add more visual noise
CAPTCHA_NOISE_FUNCTIONS = (
'captcha.helpers.noise_arcs',
'captcha.helpers.noise_dots',
'captcha.helpers.noise_dots', # Apply dots twice for more noise
)
# Apply smoothing filter
CAPTCHA_FILTER_FUNCTIONS = (
'captcha.helpers.post_smooth',
)# Enable captcha pool for high-traffic sites
CAPTCHA_GET_FROM_POOL = True
CAPTCHA_GET_FROM_POOL_TIMEOUT = 10
# Longer expiration time
CAPTCHA_TIMEOUT = 15 # 15 minutes# Enable audio captcha with custom paths
CAPTCHA_FLITE_PATH = '/opt/flite/bin/flite'
CAPTCHA_SOX_PATH = '/opt/sox/bin/sox'# Create custom challenge function
def custom_challenge():
import random
import string
# Generate uppercase letters only
chars = ''.join(random.choices(string.ascii_uppercase, k=5))
return chars, chars
# Use custom challenge
CAPTCHA_CHALLENGE_FUNCT = 'myapp.utils.custom_challenge'# Disable captcha validation for testing
CAPTCHA_TEST_MODE = True # Only use in development/testing!All configuration settings have sensible defaults:
Install with Tessl CLI
npx tessl i tessl/pypi-django-simple-captcha