Skip to main content

A powerful captcha verification package for discord.py bots.

Reason this release was yanked:

I got the GitHub org name wrong

Project description

Discord.py Captcha

A powerful package for discord.py v2 that allows you to easily create CAPTCHAs for Discord Servers.

license

discord buy me a coffee

Creating a CAPTCHA system on Discord can be quite challenging for some, but it doesn't have to be that way. Discord.py Captcha handles everything for you, from CAPTCHA generation and sending, to handling user responses and validity.

What is a CAPTCHA?

Put simply, a CAPTCHA is a question you have to answer to prove you are not a robot.

CAPTCHA is an acronym for:

Completely Automated Public Turing Test (to tell) Computers (and humans) Apart

To learn more about what a CAPTCHA is, you can watch this video by Tom Scott.

What do the CAPTCHAs look like?

Below is an image of what answering a CAPTCHA will look like when using the default settings:

Image of Captcha

Installation

pip install discord.py-captcha

This will automatically install the required dependencies: discord.py v2 and Pillow.

Quick Start

import discord
from discord.ext import commands
from discord_captcha import Captcha, CaptchaOptions

intents = discord.Intents.default()
intents.message_content = True  # enable "Message Content Intent" in the dev portal!
intents.members = True

bot = commands.Bot(command_prefix="!", intents=intents)

captcha = Captcha(bot, CaptchaOptions(
    role_id=123456789,
    channel_id=987654321,
    attempts=3,
    timeout=30,
))

@bot.event
async def on_member_join(member):
    await captcha.present(member)

bot.run("YOUR_BOT_TOKEN")

Configuration

All options are passed via CaptchaOptions. Every option has a default, so you only need to set the ones you want to change.

Options Reference

Option Type Default Description
role_id int | None None The ID of the role to give the user when they solve the CAPTCHA. If None, no role is added.
channel_id int | None None The ID of a text channel to use as a fallback if the user's DMs are closed. If send_to_text_channel is True, the CAPTCHA is always sent here instead of DMs. Required if send_to_text_channel is True.
send_to_text_channel bool False When True, the CAPTCHA is always sent to the text channel specified by channel_id, bypassing DMs entirely. When False, the bot tries DMs first and only falls back to the text channel if DMs are locked.
kick_on_failure bool True Whether to automatically kick the user from the server if they fail the CAPTCHA or run out of time.
case_sensitive bool True Whether the user's answer must match the exact casing of the CAPTCHA text. When False, the CAPTCHA only generates lowercase characters and answers are compared case-insensitively.
attempts int 1 How many tries the user gets to solve the CAPTCHA before it counts as a failure. Each attempt has its own timeout window.
timeout float 60.0 How many seconds the user has to respond on each attempt before it times out.
show_attempt_count bool True Whether to display the remaining number of attempts in the embed footer. When the user only has one attempt, it shows "You have one attempt to solve the CAPTCHA." instead of a counter.
custom_prompt_embed discord.Embed | None None A custom embed to use for the CAPTCHA prompt message. If not provided, a default embed is used. The CAPTCHA image is automatically attached regardless. If show_attempt_count is enabled, the footer will be overwritten with the attempt counter.
custom_success_embed discord.Embed | None None A custom embed to show when the user solves the CAPTCHA. If not provided, a default green "CAPTCHA Solved!" embed is used.
custom_failure_embed discord.Embed | None None A custom embed to show when the user fails the CAPTCHA (wrong answers or timeout). If not provided, a default red "You Failed to Complete the CAPTCHA!" embed is used. The correct answer is shown in the default embed.

Example Configurations

Minimal — just verify, no role, no kick:

captcha = Captcha(bot, CaptchaOptions(
    kick_on_failure=False,
))

Strict — one attempt, case-sensitive, 15 second timeout:

captcha = Captcha(bot, CaptchaOptions(
    role_id=123456789,
    attempts=1,
    timeout=15,
    case_sensitive=True,
))

Lenient — multiple attempts, case-insensitive, sent in a channel:

captcha = Captcha(bot, CaptchaOptions(
    role_id=123456789,
    channel_id=987654321,
    send_to_text_channel=True,
    case_sensitive=False,
    attempts=5,
    timeout=120,
    kick_on_failure=False,
))

Usage

Presenting a CAPTCHA (Built-In Generation)

The simplest way to use this package. A CAPTCHA image is generated automatically and sent to the user.

@bot.event
async def on_member_join(member):
    result = await captcha.present(member)
    # result is True if solved, False if failed/timed out

Presenting a CAPTCHA (Custom Image)

If you want to provide your own CAPTCHA image, pass a CaptchaImageData object to present:

from discord_captcha import CaptchaImageData

@bot.event
async def on_member_join(member):
    with open("my_captcha.png", "rb") as f:
        image_bytes = f.read()

    await captcha.present(member, CaptchaImageData(
        image=image_bytes,
        text="the_answer"
    ))

Manually Creating a CAPTCHA

You can use the create_captcha function to generate a CAPTCHA image without presenting it. This gives you control over the character length and which characters to exclude.

The character pool is A-Z, a-z, and 0-9 by default. Pass a blacklist string to exclude specific characters.

from discord_captcha import create_captcha

# 4 characters, no numbers
my_captcha = await create_captcha(4, blacklist="0123456789")
# => CaptchaImageData(image=b'...', text='aBCd')

# pass it to present
await captcha.present(member, my_captcha)

Events

Events let you hook into the CAPTCHA lifecycle for logging, analytics, or custom behavior. Register them as decorator callbacks on the Captcha instance.

Every callback receives a CaptchaEventData object with the following attributes:

Attribute Type Description
member discord.Member The member who is being presented the CAPTCHA.
captcha_text str The correct answer to the CAPTCHA.
captcha_options CaptchaOptions The options the CAPTCHA was configured with.
responses list[str] All answers the user has submitted so far. Empty for on_prompt.
attempts int How many attempts have been taken so far. 0 for on_prompt.

Available Events

on_prompt — Called when the CAPTCHA is first sent to the user, before they've had a chance to respond.

on_answer — Called every time the user submits a response, whether it's correct or not. Useful for logging individual attempts.

on_success — Called when the user answers correctly. At this point the role has already been added (if configured).

on_failure — Called when the user exhausts all their attempts with wrong answers. At this point the user has already been kicked (if configured).

on_timeout — Called when the user doesn't respond within the timeout window. At this point the user has already been kicked (if configured).

Example

@captcha.on_prompt
async def on_prompt(data):
    print(f"CAPTCHA sent to {data.member} (answer: {data.captcha_text})")

@captcha.on_answer
async def on_answer(data):
    print(f"{data.member} answered: {data.responses[-1]} (attempt {data.attempts})")

@captcha.on_success
async def on_success(data):
    print(f"{data.member} solved it in {data.attempts} attempt(s)")

@captcha.on_failure
async def on_failure(data):
    print(f"{data.member} failed after {data.attempts} attempt(s). Answers: {data.responses}")

@captcha.on_timeout
async def on_timeout(data):
    print(f"{data.member} didn't respond in time")

Contact Us


Created and maintained by Diamond Digital Development Logo

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

discord_py_captcha-1.0.0.tar.gz (249.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

discord_py_captcha-1.0.0-py3-none-any.whl (14.1 kB view details)

Uploaded Python 3

File details

Details for the file discord_py_captcha-1.0.0.tar.gz.

File metadata

  • Download URL: discord_py_captcha-1.0.0.tar.gz
  • Upload date:
  • Size: 249.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for discord_py_captcha-1.0.0.tar.gz
Algorithm Hash digest
SHA256 200a79ac4421001b92d3989b0f25f5929815268ebf854383f79aea3b0a23c5c4
MD5 5498a89f9d6788a519d00c09e3f53a16
BLAKE2b-256 48e7dfd203b5a451261be2aa45415dfacd7c8cd8ef4e2982c2b3e3b13c05dcc6

See more details on using hashes here.

File details

Details for the file discord_py_captcha-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for discord_py_captcha-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3213af3c662a34317b6960255c9e268aff5e3b42d73fcd9265b5c87f79e6a03f
MD5 9415a4a6fa3c75eadbf84004dd085586
BLAKE2b-256 be751c5a27133471079c0d9ede2d86c1649bb70412f7ec7c88a5ab989193c112

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page