Skip to content

Puzzle CAPTCHAs

Sepehr0Day edited this page Jun 13, 2026 · 2 revisions

Puzzle CAPTCHAs

SliderPuzzleCaptcha

Move a rectangular piece horizontally into its missing slot.

from CaptchaGenerator import CaptchaConfig, SliderPuzzleCaptcha

result = SliderPuzzleCaptcha(
    CaptchaConfig(width=720, height=420, random_seed=42)
).generate(
    image_path="./images/photo.png",
    name_export="slider",
    path_export="./output",
    difficulty="hard",
    tolerance=10,
)

print("Background:", result.metadata["background_path"])
print("Piece:", result.metadata["piece_path"])
print("Initial x:", result.metadata["piece_start_x"])
print("Piece y:", result.metadata["target_y"])

# Final center/placement x received from the slider UI.
user_x = 410
solved = abs(user_x - result.answer) <= result.metadata["tolerance"]
print("Solved:", solved)

Send only public image files and safe layout metadata to the client. Keep target_x and result.answer server-side.

IrregularPuzzleCaptcha

Uses an irregular polygon piece. An image is optional because the generator can create a procedural background.

from CaptchaGenerator import CaptchaConfig, IrregularPuzzleCaptcha

result = IrregularPuzzleCaptcha(
    CaptchaConfig(width=800, height=480, random_seed=42)
).generate(
    image_path=None,
    name_export="irregular",
    path_export="./output",
    vertices=9,
    piece_radius=55,
    tolerance=12,
)

print("Background:", result.metadata["background_path"])
print("Piece:", result.metadata["piece_path"])
print("Start x:", result.metadata["piece_start_x"])

user_x = 500
solved = abs(user_x - result.answer) <= result.metadata["tolerance"]
print("Solved:", solved)

In a GUI, display the PNG piece with transparency over the background and move it only along the horizontal axis.

PatternCompletionCaptcha

The user selects the numbered shape that completes a repeating pattern.

from CaptchaGenerator import CaptchaConfig, PatternCompletionCaptcha

result = PatternCompletionCaptcha(
    CaptchaConfig(width=900, height=480, random_seed=42)
).generate(
    name_export="pattern",
    path_export="./output",
    pattern_length=8,
    option_count=4,
)

print("Show image:", result.path)
print("Question:", result.prompt)
print("Option count:", len(result.metadata["options"]))

# UI labels options 1..N, while the answer is zero-based.
user_option_number = 2
user_option_index = user_option_number - 1
solved = user_option_index == result.answer
print("Solved:", solved)

Do not expose pattern, missing_index, or the answer option to an untrusted client.

MazeCaptcha

Generate with answer_mode="directions" for interactive arrow controls.

from CaptchaGenerator import CaptchaConfig, MazeCaptcha

result = MazeCaptcha(
    CaptchaConfig(width=900, height=600, random_seed=42)
).generate(
    name_export="maze",
    path_export="./output",
    columns=14,
    rows=9,
    answer_mode="directions",
)

print("Show image:", result.path)
print("Question:", result.prompt)

# Directions collected from Up/Down/Left/Right buttons.
user_moves = ["right", "right", "down"]
solved = user_moves == result.answer
print("Solved:", solved)

Other answer modes:

path_result = MazeCaptcha().generate(
    name_export="maze_path",
    path_export="./output",
    answer_mode="path",
)

exit_result = MazeCaptcha().generate(
    name_export="maze_exit",
    path_export="./output",
    answer_mode="exit",
)

The Maze path and directions are private server-side solution data.

Clone this wiki locally